Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ vector member initialization

Tags:

c++

I am confused about the output in the following program about the vec in Test. Why it's a vector with size 100 instead of 1? I thought std::vector<T> var{a} is the same as std::vector<T> var = {a}.

#include <iostream>
#include <vector>

using namespace std;
struct Value {
   int a;
   int b;
};

class Test {
  public:
    std::vector<struct Value> vec{100};  
};

class Test2 {
  public:
    std::vector<int> vec{100};  
};

int main()
{
    Test test;
    std::cout << "test size: " << test.vec.size() << std::endl;
    Test2 test2;
    std::cout << "test2 size: " << test2.vec.size();
    
    return 0;
}

Output:

test size: 100
test2 size: 1
like image 730
Zack Avatar asked Feb 25 '26 03:02

Zack


1 Answers

std::vector has a constructor with a std::initializer_list<T> argument. When using an initializer list like {100} this constructor will always take priority, if it is applicable.

For a std::vector<int> the initializer {100} is compatible with std::initializer_list<int> so that constructor will be used. It will create a vector containing the collection {100} which is a single int with the value 100.

For std::vector<Value> the initializer {100} is NOT compatible with a std::initializer_list<Value> argument. Value has no converting constructor for turning an int to a Value so you cannot construct a std::initializer_list<Value> from {100}. You can verify that this conversion is not allowed with this example. The compiler will try to take a lower priority constructor instead, and will use the constructor which initializes 100 default constructed Value.

If you add a Value::Value(int) constructor or use {{100}} as the initializer for Test2 you will find that the std::vector<Value> will now only contain a single element. In both cases, the initializer list is convertible to std::initializer_list<Value> and that constructor will now be used.

like image 75
François Andrieux Avatar answered Feb 26 '26 15:02

François Andrieux