Can someone explain the difference in behavior between initializing with double and single curly braces in the example below?
Code #1:
vector<string> v = {"a", "b"};
string c(v[0] + v[1]);
cout << "c = " << c;
cout << "c.c_str() = " << c.c_str();
Output #1:
c = ab
c.c_str() = ab
Code #2:
vector<string> v = {{"a", "b"}};
string c(v[0] + v[1]);
cout << "c = " << c;
cout << "c.c_str() = " << c.c_str();
Output #2:
c = a\acke�Z\
c.c_str() = a
Implicit conversion central. That's what's going on.
vector<string> v = {"a", "b"};
You initialize the vector by providing an initializer list with two elements. The two std::string
s are initialized from the string literals, and then copied into the vector.
vector<string> v = {{"a", "b"}};
You initialize the vector by providing an initializer with one element. And that single std::string
is initialized from an initializer that has two elements. Accessing the second element of the vector has undefined behavior.
Now, here's the fun part. Your second snippet has undefined behavior even before you access v[1]
. Overload resolution (to construct the single std::string
) picks a constructor. The best viable one, is this:
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
With InputIt
being deduced as char const [2]
(and function parameter adjustment, turning it to char const*
). Since those aren't really iterators, all hell breaks loose.