为什么此代码将字符串初始化为单个字符时调用initializer_list构造函数?

问题描述:

我最近正在研究一个C++项目,并遇到了一个我不能完全理解的字符串构造函数的边界案例。相关的代码(其you can run here)如下:为什么此代码将字符串初始化为单个字符时调用initializer_list构造函数?

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string directParens(1, '*'); 
    string directBraces{1, '*'}; 
    string indirectBraces = {1, '*'}; 

    cout << directParens.size() << endl; // 1 
    cout << directBraces.size() << endl; // 2 
    cout << indirectBraces.size() << endl; // 2 
    return 0; 
} 

琴弦的支架初始化版本最终不得不在他们的两个字符,即,具有数值1 char后跟一个星。

我不明白为什么字符串的大括号初始化版本调用initializer_list构造函数而不是构造函数需要大小和字符。该initializer_list构造有这样的签名:

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

鉴于stringbasic_string字符的别名,具体的签名会

string(std::initializer_list<char> init, 
     const Allocator& alloc = Allocator()); 

如何初始化{1, '*'},其中包含的元素int类型都和类型为char,与此构造函数匹配?我的印象是,std::initializer_list中的所有文字必须具有相同的字体 - 这是不正确的吗?

+1

请注意,缩小转换有一个例外[对于常量表达式,其转换后的结果将符合目标类型](https://stackoverflow.com/a/26974911/1708801) –

初始值设定项{1,'*'}如何与此构造函数匹配,包含int类型和char类型的元素?

由于字面1和字符'*'两者都转换为char不使用收缩转换。因此,他们有资格拨打initializer_list<char>构造函数。和initializer_list构造函数总是使用列表初始化时有优先权。如果可以从参数调用initializer_list构造函数,那么它将会。

切勿使用支撑-INIT-名单与除非你打算在列表中的元素容器元素的容器的。如果你打算将它们作为构造函数参数,则使用构造函数。

+0

啊,呃。因此,如果所有元素都可以转换为基础类型而不缩小转换,则大括号初始化器将被解释为initializer_list。为了确认,这是否意味着{3,3.0}可以被解释为initializer_list ,但不是initializer_list ?而且{INT_MAX,'*'}可能是一个初始化表列表? – templatetypedef

+0

@templatetypedef:那么,'{INT_MAX,'*'}'示例*不能*为'initializer_list ',因为'INT_MAX'不能在没有缩小转换的情况下转换为'char'。但除此之外,你是对的。 –

+0

哦,我认为缩小转换适用于*类型*,而不是*值。*清除了一些东西!谢谢! – templatetypedef