2017-10-04 47 views
3

考虑以下示例代码初始化: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; 
} 

产生以下输出:

element print 
element print 
vector print 
vector print 

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

这是部分讨论的in an other question其中提供的解决方案适用于具有多个元素的向量。

回答

6

因为在过载分辨率print({2});所述第一过载胜。

在这两种情况下copy list initialization适用,为第1过载服用int

(重点煤矿)

否则(如果T不是类类型),如果支撑-初始化列表只有一个元素,并且T不是引用类型或者是与元素类型兼容的引用类型,所以T被直接初始化(在直接列表初始化中)或者拷贝初始化(在拷贝中)列表初始化),exce pt缩小转换是不允许的。

{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)是必需的,那么它的匹配比第一个重载更差。

8

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

2

不,你不是在创建一个initializer_list。

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

呼叫1)单元被称为

呼叫2)initializer_list创建单个int元件

呼叫3)矢量对象是以给定的

呼叫4)一个Vector对象被给出

Overload resulotion倾向于在std :: vector之前使用int参数方法参数方法,因为有更少的类型转换。 int参数是直接匹配,对于vector参数需要额外的转换。

例如:

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

将导致用于呼叫2,即输出为“initializer_list打印”

+1

重要提示:支撑初始化器列表是*无类型*,而不是'std :: initializer_list'。所以你的第一句话是错误的。 – Rakete1111