I have a C++ snippet that looks like this:
std::list<std::vector<int>> lv;
lv.push_back({});
std::cout << lv.size() << std::endl; // "1"
lv.insert(lv.end(), {}); // Oops!
// lv.insert(lv.end(), std::vector<int>()); // OK
std::cout << lv.size() << std::endl; // Still got "1", but why?
As you can see, when using {}
to create a default std::vector<int>
, the insertion didn't happen at all. While I know that there are lots of subtleties when using C++'s initializer list, I wonder what is the problem in this example?
Thanks!
When do we use Initializer List in C++? Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T .
Overload resolution for the
lv.insert(lv.end(), {}); // Oops!
call will resolve (formally, chosen as the best viable function as per [over.ics.rank]/3.1) to the following std::list<>::insert
overload [extract from std::list<>::insert
at cppreference, emphasis mine]:
iterator insert( const_iterator pos, std::initializer_list<T> ilist );
inserts elements from initializer list ilist before pos.
But as the initializer list is empty, there are no elements from it to be inserted.
You could likewise invoke the same insert
overload with a nested list initialization within the list initialization,
lv.insert(lv.end(), {{}}); // Size is now 2.
such that the innermost list initialization will resolve to (as per [over.match.list]/1) the std::initializer_list
constructor of std::vector
:
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
in so inserting a single element of type std::vector<int>
, specifically an an empty such vector, into the std::list<std::vector<int>>
object.
When you call push_back
, the {}
argument is deduced to be the element type of the list, so a single vector
gets inserted into the list.
When you call insert
, you are using the initializer list overload, and since the initializer list is empty, no elements get added to the list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With