c ++ 11函数调用中的单元素向量初始化

Imr*_*ran 6 c++ stl vector overload-resolution c++11

请考虑以下示例代码:

例:

void print(int n) {
    cout << "element print\n";
}

void print(vector<int> vec) {
    cout << "vector print\n";
}

int main() {
   /* call 1 */ print(2);
   /* call 2 */ print({2});
   std::vector<int> v = {2};
   /* call 3 */ print(v);
   /* call 4 */ print( std::vector<int>{2} );
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

它生成以下输出:

element print
element print
vector print
vector print
Run Code Online (Sandbox Code Playgroud)

为什么print函数调用(上例中的调用2)与接受单个值的函数匹配?我在这个调用中创建了一个向量(包含单个元素),所以它与print使用向量作为输入的调用不匹配吗?

在另一个问题中进行了部分讨论,其中所提供的解决方案适用于具有多于1个元素的向量.

son*_*yao 9

因为第一次重载在重载决策中获胜print({2});.

在这两种情况下,复制列表初始化适用于第一次过载int,

(强调我的)

否则(如果T不是类类型),如果braced-init-list只有一个元素,并且要么T不是引用类型,要么是与元素类型兼容的引用类型,T则直接初始化(在直接列表初始化)或复制初始化(在复制列表初始化中),但不允许缩小转换.

{2}只有一个元素,它可以用来直接初始化一个int参数; 这是完全匹配.

对于第二次超载std::vector<int>,

否则,将分T两个阶段考虑构造函数:

  • std::initializer_list作为唯一参数的所有构造函数,或者如果其余参数具有默认值,则作为第一个参数,将检查所有构造函数,并通过重载解析与单个参数类型进行匹配std::initializer_list

这意味着std::initializer_list<int>构造并使用构造函数的参数std::vector<int>(构造参数print).需要一个用户定义的转换(通过构造std::vector一个std::initializer_list),然后它比第一个重载更糟糕.


Cal*_*eth 8

{2}是一种合法的初始化程序,适用于多种类型,包括int.重载分辨率更喜欢与需要进一步构造的类型完全匹配的类型.