这里发挥作用的是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
字符。