函数调用中的单元素向量初始化
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
),那么它比第一个重载更差。
考虑以下示例代码:
示例:
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 eitherT
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 typestd::initializer_list
这意味着构造了一个std::initializer_list<int>
并用作std::vector<int>
的构造函数参数(构造print
的参数)。需要一个用户定义的转换(通过 std::vector
的构造函数进行一个 std::initializer_list
),那么它比第一个重载更差。