2017-04-09 120 views
2

考虑下面的代码为什么调用转发引用构造函数而不是复制构造函数?

#include <iostream> 

using namespace std; 

template <typename Type> 
struct Something { 
    Something() { 
     cout << "Something()" << endl; 
    } 

    template <typename SomethingType> 
    Something(SomethingType&&) { 
     cout << "Something(SomethingType&&)" << endl; 
    } 
}; 

int main() { 
    Something<int> something_else{Something<int>{}}; 
    auto something = Something<int>{}; 
    Something<int>{something}; 
    return 0; 
} 

我得到以下输出

Something() 
Something() 
Something(SomethingType&&) 

为什么拷贝构造函数解析成模板转发参考构造函数,但不是移动构造函数?我猜测这是因为移动构造函数是隐式定义的,而不是复制构造函数。但是在阅读堆栈溢出中未隐式定义拷贝构造函数的情况后,我仍然感到困惑。

+1

这是一个体面的共同话题博客:https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/ – chris

回答

4

我猜测这是因为移动构造函数是隐式定义的,而不是复制构造函数。

不,这两者都是为Something类别隐式定义的。

,就是因为拷贝构造函数采用const Something&作为其参数拷贝构造函数解析成模板转发参考构造

。这意味着要调用复制构造函数,需要隐式转换才能添加const限定符。但是转发参考构造函数可以被实例化采取Something&作为它的参数,那么它的精确匹配,胜在重载决议。

因此,如果您制作somethingconst,则将针对第三种情况而不是转发引用构造函数调用隐式定义的复制构造函数。

LIVE

而不是移动构造函数?

因为对于移动构造函数上述问题并不重要。对于第一种和第二种情况的调用,隐式定义的移动构造函数和转发引用构造函数是完全匹配的,然后非模板移动构造函数获胜。

+3

一本书,我了解这些类型的问题,发现是非常有益的[ Effective Modern C++](http://shop.oreilly.com/product/0636920033707.do)作者:Scott Meyers。 –