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

Single-Element-Vector Initialization in a Function Call

考虑以下示例代码:

示例:

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

生成以下输出:

element print
element print
vector print
vector print

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

对此进行了部分讨论 in an other question,其中提供的解决方案适用于具有 1 个以上元素的向量。

{2} 是许多类型的合法初始值设定项,包括 int。重载解析更喜欢与需要进一步构造的类型完全匹配的类型。

不,那不是你所做的,你正在创造一个 initializer_list。

参见:http://en.cppreference.com/w/cpp/utility/initializer_list

调用 1) 单个元素被调用

调用 2) initializer_list 创建单个 int 元素

调用 3) 给定一个 Vector 对象

调用 4) 给定一个 Vector 对象

Overload解决方案优先使用int参数方式,而不是std::vector参数方式,因为类型转换较少。 int参数直接匹配,vector参数需要额外转换。

例如:

void print(std::initializer_list<int> list){
    cout << "initializer_list print\n";
}

调用 2 的结果是 "initializer_list print"

因为第一个重载在 print({2}); 的重载决议中获胜。

在这两种情况下,copy list initialization 适用,第一个过载 int

(强调我的)

Otherwise (if T is not a class type), if the braced-init-list has only one element and either T isn't a reference type or is a reference type that is compatible with the type of the element, T is direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.

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

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

Otherwise, the constructors of T are considered, in two phases:

  • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list

这意味着构造了一个std::initializer_list<int>并用作std::vector<int>的构造函数参数(构造print的参数)。需要一个用户定义的转换(通过 std::vector 的构造函数进行一个 std::initializer_list),那么它比第一个重载更差。