为什么这段将字符串初始化为单个字符的代码会调用 initializer_list 构造函数?

Why does this code to initialize a string to a single character call the initializer_list constructor?

我最近在做一个 C++ 项目,遇到了一个我无法完全理解的字符串构造函数的边缘情况。相关代码(其中you can run here)如下:

#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;
}

字符串的大括号初始化版本最终有两个字符,即 char,数值 1 后跟一个星号。

我不明白为什么字符串的大括号初始化版本调用 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());

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

How is the initializer {1, '*'}, which contains elements both of type int and of type char, matching this constructor?

因为文字 1 和字符 '*' 都可以转换为 char 而无需使用缩小转换。因此,它们有资格调用 initializer_list<char> 构造函数。并且 initializer_list 构造函数 always 在使用列表初始化时具有优先权。如果可以从参数调用 initializer_list 构造函数,那么它会。

永远不要对容器使用 braced-init-lists 除非您希望列表中的元素成为容器的元素。如果您希望它们成为构造函数参数,请使用构造函数。