Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does 'std::vector<int> b{2};' create a 1-element vector, and not a 2-element one?

I've been playing around with C++11 for the past few days, and I came up with something strange.

If I want to uniformly initialize an int:

int a{5}; 

But if I do the same thing to a std::vector:

std::vector<int> b{2}; 

Does not construct a two element array, but rather an array with one element of value two. It seems like to get that effect one would need to be more explicit about it:

std::vector<int> c{{2}}; std::vector<int> d = {2}; 

But not like the declaration of b - this seems inconsistent. I have seen some other stuff to the same effect. What I'm asking - is this behavior in the final C++11 standard, or is it just in a draft that was implemented early? If so, why did the standards committee include this behavior? It seems like it defeats the whole purpose of uniform initialization, as one has to remember which classes have initializer list constructors, and to use the old () syntax instead of {} with just those classes. Or one forgoes uniform initialization altogether.

This seems like a big "gotcha". But there might be advantages to it that I am not aware of.

Edit: this code:

#include <iostream> #include <vector>  int main() {     std::vector<int> a{2};     for (auto x: a) {         std::cout << x << std::endl;     }     return 0; } 

outputs "2" on gcc 4.6.2

like image 353
Robert Mason Avatar asked Mar 15 '12 15:03

Robert Mason


People also ask

Can we add 2 vectors in C++?

The simplest solution is to use a copy constructor to initialize the target vector with the copy of all the first vector elements. Then, call the vector::insert function to copy all elements of the second vector. We can also use only vector::insert to copy elements of both vectors into the destination vector.

How are elements added to a vector?

Conclusion. A single element can be appended to a vector with the push_back() and emplace_back() vector member functions. The insert() member function can also be used in its different overloaded forms. The insert() function works with iterators.

What does std::vector do?

1) std::vector is a sequence container that encapsulates dynamic size arrays. 2) std::pmr::vector is an alias template that uses a polymorphic allocator. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements.


1 Answers

Yes, this behaviour is intended, according to §13.3.1.7 Initialization by list-initialization

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.

— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

As to "the whole purpose of uniform intialization"... "Uniform initialization" is a marketing term, and not a very good description. The standard has all the usual forms of initialization plus list-initialization, but no "uniform initialization". List initialization is not meant to be the ultimate form of initialization, it's just another tool in the utility belt.

like image 54
R. Martinho Fernandes Avatar answered Sep 28 '22 02:09

R. Martinho Fernandes