Poperton
Poperton

Reputation: 2127

Why does brace initialization in C++ solve the problem of initialization of STL containers?

I'm reading Effective Modern C++, in the section about brace initialization.

Even with several initialization syntaxes, there were some situations where C++98 had no way to express a desired initialization. For example, it wasn’t possible to directly indicate that an STL container should be created holding a particular set of values (e.g., 1, 3, and 5)

Then he shows:

std::vector<int> v{ 1, 3, 5 }; // v's initial content is 1, 3, 5

Why wasn't it possible to do

std::vector<int> v(1,3,5) 

before? How is the constructor of a class that accepts brace initialization different?

Upvotes: 5

Views: 604

Answers (3)

pcodex
pcodex

Reputation: 1940

std::vector<int> v(1,3,5) 

It still isn't possible to do the above and that's because when you try to list initialize the standard expects that you use curly braces.

And for this

MyType obj1, obj2;
std::vector<MyType> v{ obj1, obj2 };
//std::vector<MyType> v = { obj1, obj2 }; //similar

if you consider the non-built in types it will become very obvious how list initialization works. In the case above the copy constructor comes into play twice for each element being initialized into the vector. First obj1 is copy constructed into a temporary and this temporary is then copied once again into the vector.

Consider the similarity in syntax to regular copy construction.

class Type {}

Type obj1;
Type obj2{obj1};
Type obj3 = {obj1};

Upvotes: 3

eerorika
eerorika

Reputation: 238311

Why it wasn't possible to do

std::vector<int> v(1,3,5) 

Because vector didn't have a constructor that would accept 3 elements.

It would not have been practical to define a constructor for every possible number of elements to initialise. Especially since some number of arguments are ambiguous with other constructors: Single integer constructs a vector of certain size, and one integer and one element copy initialises those elements.

The introduction of std::initializer_list and its special role in the extended list initialisation in C++11 made std::vector<int> v{ 1, 3, 5 } possible.

How different is the constructor of a class that accepts brace initialization?

In case of vector, the declaration looks like this:

vector(std::initializer_list<T> init,
    const Allocator& alloc = Allocator() );

Upvotes: 6

Bathsheba
Bathsheba

Reputation: 234665

In order to implement

std::vector<int> v(1,3,5);

, the C++98 standard library implementers would have had to provide a constructor with an arbitrarily long argument list, and the presence of the constructor to set the number of elements of a given value, and the ability to change the allocator would have been a further complications. A maximum argument limit would have had to been agreed upon. It could have also been ambiguous if you wanted a vector of allocators! All this means the idea would have been objectionable.

The constructor facilitating modern day list initialisation uses a special initialiser list object.

Upvotes: 7

Related Questions