I feel weird when I write some code below. I am looking forward to the same output, but it turns out to be wrong. Why do the 2 statements have the different output, and what's the difference between (expression-list) and {initializer-list}?
cout << string(4, 'c') << endl;
cout << string{ 4, 'c' } << endl;
the output is:
cccc
c //a square '' before 'c'
From cppreference.com:
Otherwise, the constructors of
T
are considered, in two phases:
All constructors that take
std::initializer_list
as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of typestd::initializer_list
If the previous stage does not produce a match, all constructors of
T
participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).
In your case
string(4, 'c')
uses the following constructor.
std::string(size_type count,
char ch,
const Allocator& alloc = Allocator() );
On the other hand,
string{ 4, 'c' }
uses the following constructor.
std::string(std::initializer_list<char> ilist,
const Allocator& alloc = Allocator() );
Had the second constructor not been defined in std::string
, both of those would have produced identical objects.