这里发挥作用的是direct-list-initialization具有以下语法之一的规则
T object { arg1, arg2, ... };
在这里,在 的情况下std::string s{10, 'c'},T在上面的语法中是std::string并且适用的规则是
否则,将分两个阶段考虑 T 的构造函数: 将 std::initializer_list 作为唯一参数或作为第一个参数(如果剩余参数具有默认值)的所有构造函数进行检查,并通过重载决议针对单个std::initializer_list 类型的参数
由于有一个构造函数std::string接受一个初始值设定项列表,其他参数为默认值,即构造函数 (9)
basic_string( std::initializer_list<CharT> ilist,
const Allocator& alloc = Allocator() );
参与此决议,因为10可以隐式转换为char,你得到的是std::initializer_list<char>2{'\n', 'c'}个字符。
在 的情况下std::vector<std::string> v{10. "hi"},T是std::vector<std::string>在上面提到的语法direct-list-initialization中。
现在,由于10不能隐式转换为std::string,因此std::initializer_list<std::string>不能构造这样的,因此下一个替代方法direct-list-initialization是
如果前一个阶段没有产生匹配,则 T 的所有构造函数都参与重载决议,以对抗由括号初始化列表的元素组成的参数集,并限制只允许非缩小转换。
这会产生与构造函数 3的匹配
explicit vector( size_type count,
const T& value = T(),
const Allocator& alloc = Allocator());
因为这两个转换都不是非缩小的。
现在来到你想要实现的目标std::string s{10, 'c'},应该使用std::string s(10, c)不list-initialization涉及的地方来完成。
std::string s1{10, 'c'}, s2(10, 'c');
std::cout<<'['<<s1<<']'<<'['<<s2<<']'<<'\n';
输出:
[
c][cccccccccc]
请注意,打印s1会在 the 之前生成一个新行,c因为它实际上是['\n', 'c'],而s2这正是您所期望的,即 10 个c字符。