请考虑以下示例代码:
示例:
<g class="element-group">
<g class="element">
<rect class="element-shape bundle-shape"
x="101.778125"
width="131"
y="36.44939999999999"
height="138.5466"
style="fill: rgb(230, 204, 102);
stroke-width: 0px;
stroke: rgb(0, 128, 128);">
</rect>
</g>
<g class="element">
...
</g>
<g class="element">
...
</g>
</g>
生成以下输出:
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
函数(上例中的调用2)与接受单个值的函数匹配?我在这个调用中创建了一个向量(包含单个元素),所以如果它与向量作为输入调用print
不匹配吗?
部分讨论in an other question,其中提供的解决方案适用于具有多于1个元素的向量。
答案 0 :(得分:9)
因为第一次重载在print({2});
的重载决策中获胜。
在copy list initialization适用的两种情况下,对于第一次过载int
,
(强调我的)
否则(如果
T
不是类类型),如果braced-init-list只有一个元素且T
不是引用类型或是与元素类型兼容的引用类型,T
是直接初始化(在直接列表初始化中)或复制初始化(在复制列表初始化中),除了缩小转换不是允许的。
{2}
只有一个元素,它可以用来直接初始化int
作为参数;这是完全匹配。
对于第二次过载std::vector<int>
,
否则,
T
的构造函数分为两个阶段:
- 检查所有以
std::initializer_list
为唯一参数的构造函数,或作为第一个参数(如果其余参数具有默认值),并通过重载解析与std::initializer_list
类型的单个参数进行匹配/ LI>
这意味着构造std::initializer_list<int>
并将其用作构造函数的std::vector<int>
参数(构造print
的参数)。需要进行一次用户定义的转换(通过构造函数std::vector
获取一个std::initializer_list
),然后它比第一次重载更糟糕。
答案 1 :(得分:8)
{2}
是多种类型的合法初始值设定项,包括int
。重载分辨率更喜欢与需要进一步构造的类型完全匹配的类型。
答案 2 :(得分:2)
不,那不是你做的,你正在创建一个initializer_list。
请参阅:http://en.cppreference.com/w/cpp/utility/initializer_list
调用1)调用单个元素
调用2)initializer_list创建一个int元素
调用3)给出Vector对象
调用4)给出Vector对象
Overload resulotion更喜欢在std :: vector参数方法之前使用int参数方法,因为类型转换较少。 int参数是直接匹配,对于vector参数,需要进行额外的转换。
例如:
void print(std::initializer_list<int> list){
cout << "initializer_list print\n";
}
将导致调用2,输出为&#34; initializer_list print&#34;