Why can't I use list insted of array?

I'm a beginner in C++ and I have a question
in array.
We can initialize an array like this:
 
  int arr[] = {0, 0, 4, -3, 7, 8, 2};

and use array for a parameter of a function like this:
 
  int doSomethingOnAnArray(int a[]);

but why can't I call a funtion like this:
1
2
3
4
5
6
7
int doSomethingOnAnArray(int a[]);
...
int main() {
...
doSomethingOnAnArray({1, 2, 3, 4, 5, 6});
...
}
You just can't. Arrays have been around since C. It could have potentially have been a feature, but I guess the evolution of C and C++ demonstrated otherwise.

You can, however, use an std::array or std::vector in this way.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Example program
#include <iostream>
#include <array>
#include <vector>
using std::array;
using std::vector;

int doSomethingOnAnArray(const array<int, 10>& arr)
{
    int sum = 0;
    for (int i = 0; i < 10; i++)
        sum += arr[i];
    return sum;
}

int doSomethingOnAVector(const vector<int>& arr)
{
    int sum = 0;
    for (size_t i = 0; i < arr.size(); i++)
        sum += arr[i];
    return sum;
}

int main()
{
    std::cout << doSomethingOnAnArray( {1, 2 } ) << '\n'; // NOTE: Implicitly sets elements [2]+ to 0.
    std::cout << doSomethingOnAnArray( {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } ) << '\n';

    //std::cout << doSomethingOnAnArray( {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } ) << '\n'; // ERROR: Too many elements

    std::cout << doSomethingOnAVector( {1, 2, 3 } ) << '\n';
    std::cout << doSomethingOnAVector( {1, 2, 3, 4, 5 } ) << '\n';
}


With templates, you can also do something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Example program
#include <iostream>
#include <array>
using std::array;

template <int N>
int doSomethingOnAnArray(const array<int, N>& arr)
{
    int sum = 0;
    for (int i = 0; i < N; i++)
        sum += arr[i];
    return sum;
}

int main()
{
    std::cout << doSomethingOnAnArray<2>( { 1, 2 } ) << '\n'; // forms array<int, 2>
    std::cout << doSomethingOnAnArray<10>( { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } ) << '\n'; // forms array<int, 10>
    std::cout << doSomethingOnAnArray<14>( { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } ) << '\n'; // forms array<int, 14>
}


PS: Almost forgot to mention, the feature you're referring to is called "initializer list" (not to be confused with constructor initialization lists).
Last edited on
Oh, thanks. I got it.
1
2
3
4
5
6
int doSomething( int* arr );

int main()
{
    std::cout << doSomething( { 1, 2 } ) << '\n';
}

 In function 'int main()':
error: cannot convert '<brace-enclosed initializer list>' to 'int*' for argument '1' to 'int doSomething(int*)'

The int* and int[] should be interchangeable an parameter list:
int doSomething( int[] arr );
error: expected ',' or '...' before 'arr'
 In function 'int main()':
error: cannot convert '<brace-enclosed initializer list>' to 'int*' for argument '1' to 'int doSomething(int*)'

Stating the size of array does not help either:
int doSomething( int[2] arr );
error: expected ',' or '...' before 'arr'
 In function 'int main()':
error: cannot convert '<brace-enclosed initializer list>' to 'int*' for argument '1' to 'int doSomething(int*)'


Whether we write int*, int[], or int[2], the compiler sees int*.
On the other hand, { 1, 2 } is a <brace-enclosed initializer list>.

One more try:
1
2
3
4
int main()
{
    int* arr = { 1, 2 };
}

 In function 'int main()':
3:23: error: scalar object 'arr' requires one element in initializer

Different words, but it still says: "How am I supposed to squeeze all that into one value?"


Your compiler does say what it thinks to be a problem. Some is just about syntax, some not.
@keskiverto, but I can't do this either:
1
2
int *p = new int[2];
p = {1, 2};

This time p has enough space to contains two value.
1
2
3
4
5
6
7
#include <iostream>

int main()
{
   int *arr = new int[2]{ 1, 2 };
   std::cout << arr[0] << ' ' << arr[1] << '\n';
}



or

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <vector>

int main()
{
   std::vector<int> arr(2);
   arr = { 1, 2 };
   std::cout << arr[0] << ' ' << arr[1] << '\n';
}
Last edited on
Er. That's good. But you didn't answer my question.(or is this also about syntax?)
MILLER XYL wrote:
But you didn't answer my question.(or is this also about syntax?)

You asked this question (albeit not of me):
@keskiverto, but I can't do this either:
int *p = new int[2];
p = {1, 2};
This time p has enough space to contains two value.

I attempted to answer it.



Your p is a pointer. You can't assign a pointer to an initialiser list. And the "initialiser" in initialiser list means precisely that.

Other standard arrays have a nasty tendency to decay to pointers, too.

c++ doesn't necessarily work like other languages.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>

int main()
{
   int *arr = new int[2]{ 1, 2 };    // OK

// int arr[2] = { 1, 2 };            // OK

// int arr[2]{ 1, 2 };               // OK

// std::vector<int> arr{ 1, 2 };     // OK

// std::vector<int> arr;             // |OK
// arr = { 1, 2 };                   // |

// int arr[2];                       // |Not OK
// arr = { 1, 2 };                   // | 

   std::cout << arr[0] << ' ' << arr[1] << '\n';
}
> why can't I call a function like this
> doSomethingOnAnArray({1, 2, 3, 4, 5, 6});

To create prvalue of an array type, we need to use a brace-initialized functional cast
https://en.cppreference.com/w/cpp/language/array#Array_rvalues

This is fine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using array_type = int[5] ;

void doSomethingOnAnArray( const array_type& arr )
{
    std::cout << "{ " ;
    for( int v : arr ) std::cout << v << ' ' ;
    std::cout << "}\n" ;
}

int main()
{
    // A single-word type name followed by a braced-init-list is a prvalue of the specified type ...
    // This is the only cast expression that can create an array prvalue.
    // https://en.cppreference.com/w/cpp/language/explicit_cast (5)
    doSomethingOnAnArray( array_type{ 1, 2, 3 } ) ;
}

http://coliru.stacked-crooked.com/a/5ce470072a3dc819
https://rextester.com/PYET59613
C-arrays are simple things.
They are nothing more than a pointer to a fixed size block of memory. They are NOT objects, and this is the 'why' behind it, they can't do what objects can do because they are not objects :)

The compiler 'could' be back coded to start supporting some of these ideas, but that is unlikely to happen. Arrays predate objects, in C, and predate the STL and modern ideas.

- you can't resize it
- you can't assign, compare, or use other operators on it 'for all elements'
- it has a fixed size at compile time
- you can't delete to resize it or delete in the middle and have it automatically scoot the data.
- it does not know its own size
- it does not have iterators
and so on.
All these things can be done with a vector (though delete in the middle takes a bit of hand waving, its still one line of code), so if you want an objectified array, you have one available, and it is usually recommended to use a vector so you CAN get these tools.
Last edited on
jonnin, C-arrays are objects distinct from pointers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Example program
#include <iostream>
#include <typeinfo>

void pass_array(int(&arr)[10]) { }

int main()
{
    int arr[10];
    
    int* ptr =  arr;
    std::cout << typeid(arr).name() << '\n'
              << typeid(ptr).name() << '\n'
              << sizeof(arr) << '\n'
              << sizeof(ptr) << '\n';
    
    pass_array(arr);
    //pass_array(ptr); // error
}

A10_i  // "Array of 10 ints"
Pi    // "Pointer to int"
40
8

If it were just a pointer, then something like keskiverto's example would work
1
2
3
4
int main()
{
    int* arr = { 1, 2 };
}

Maybe I'm being pedantic but meh.
Last edited on
I suppose it depends on how you define an object. Arrays are distinct from pointers (agreed!) but both are still just an address and an offset and are more alike than different. If you are coming from newer languages where 'arrays' in those languages are objects and are like what we call vectors, its critical to make a distinction. How pedantic you want to get on that is up to you :)
Last edited on
An object of an array type is an object that contains sub-objects (array elements).
An object of an class type is an object that may contain sub-objects (member sub-objects and base class sub-objects).
It's clear now. Thanks to you all!
Topic archived. No new replies allowed.