当移动和复制构造函数都存在时,将调用哪一个?

时间:2014-12-26 18:26:14

标签: c++ copy move language-lawyer

下面是A类,它充满了不同类型的构造函数。 如果我对移动构造函数进行注释,则复制构造函数被调用两次:一次是通过值传递一个对象来实现函数的乐趣,另一次是从同一个函数返回。

代码段

A级{

int x;

public :
A() {
    cout<<"Default Constructor\n";
}

A(A&& a) : x(a.x){
    cout<<"Move Constructor\n";
    a.x=0;
}

A(const A& a){
    x=a.x;
    cout<<"Copy Constructor\n";
}

A fun(A a){
    return a;
}

};

int main(){

A a;
A b;
A c;
c=a.fun(b);

}

输出:

Default Constructor

Default Constructor

Default Constructor

Copy Constructor

Move Constructor

但是,如果存在移动构造函数,则调用它而不是复制构造函数。任何人都可以用一个很好的例子来阐述这一点,这样我就可以清楚这个概念。

感谢您的帮助。谢谢。

2 个答案:

答案 0 :(得分:8)

该标准允许特殊情况用于return语句中的表达式是自动持续时间变量的情况。在这种情况下,选择构造函数重载,就像return中的表达式是rvalue一样。

更准确地说,如果return语句中的表达式是一个自动持续时间变量,它有资格进行复制省略,或者如果你忽略了它是一个函数参数的事实,那么,编译器为了超载分辨的目的,需要将其视为右值。请注意,在C ++ 11中,return语句的表达式需要将cv-unqualified类型作为函数返回类型。这在C ++ 14中有所放松。

例如,在C ++ 11中,以下代码调用A的复制构造函数,而不是移动构造函数:

class A
{
};

class B
{
public:
B(A a) : a(std::move(a)){}
A a;
};

B f(A a)
{
return a;///When this is implicitly converted to `B` by calling the constructor `B(a)`, the copy constructor will be invoked in C++11. This behaviour has been fixed in C++14.
}

答案 1 :(得分:4)

在函数A fun(A a)中传入的“副本”A基本上是一个临时变量。如果没有移动构造函数,则返回值是副本(即复制构造函数)。

如果有一个移动构造函数,那么编译器可以在临时变量“A a”上执行更有效的“移动”系统化。