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

时间:2017-10-04 12:41:44

标签: c++ c++11 vector stl overload-resolution

请考虑以下示例代码:

示例:

<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个元素的向量。

3 个答案:

答案 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;