1

我正在阅读 c++ 入门并遇到了一个向量列表初始化的示例,其中作者提到如果无法进行列表初始化,编译器就会寻找其他方法来初始化对象。以下是字符串向量的示例。

vector<string> v8{10, "hi"};

这将创建一个包含 10 个元素的向量,其值为“hi”。我认为这是因为列表初始化依赖于下面的构造函数来创建向量。

vector( size_type count, const T& value, const Allocator& alloc = Allocator());

我为 String 尝试了类似的列表初始化

std::string s1{10, 'c'};

我期待它创建一个字符串“cccccccccc”,因为它有一个可用的构造函数

basic_string( size_type count, CharT ch, const Allocator& alloc = Allocator() );

但它只打印“c”?这里使用了哪个字符串构造函数?

4

2 回答 2

3

构造函数std::initiazer_list被调用。

constexpr basic_string( std::initializer_list<CharT> ilist,
                        const Allocator& alloc = Allocator() );

10是一个int,它可以char隐式转换为 ,并且std::initializer_list<char>可以由{10, 'c'}包含两个chars 构成,第一个具有 ASCII 值10,第二个为c

另一方面对于std::vector<std::string>,{10, "hi"}不能用于构造std::initializer_list<std::string>,因为10不能转换为std::string,那么构造函数std::initializer_list<std::string>就不会被使用。

于 2021-06-17T05:37:08.113 回答
1

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

于 2021-06-17T06:07:19.223 回答