C++ 当move和copy构造函数都存在时,将调用哪个构造函数?

C++ 当move和copy构造函数都存在时,将调用哪个构造函数?,c++,copy,move,language-lawyer,C++,Copy,Move,Language Lawyer,下面是A级,它充满了不同类型的构造函数。 如果我注释move构造函数,那么copy构造函数将被调用两次:一次是通过值将对象传递给fun函数,另一次是通过从同一函数返回 代码片段 甲级{ 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

下面是A级,它充满了不同类型的构造函数。 如果我注释move构造函数,那么copy构造函数将被调用两次:一次是通过值将对象传递给fun函数,另一次是通过从同一函数返回

代码片段

甲级{

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;
}
}

输出:

Default Constructor

Default Constructor

Default Constructor

Copy Constructor

Move Constructor
但是,如果存在移动构造函数,则会调用它而不是复制构造函数。有谁能举个好例子来证明这一点,这样我就能清楚地了解这个概念了


非常感谢您的帮助。谢谢。

对于
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.
}
在函数A中,传入的A的“副本”基本上是一个临时变量。如果没有移动构造函数,则返回值是一个副本(即复制构造函数)


如果有移动构造函数,则编译器可以对临时变量“a”执行更有效的“移动”系统分类。

为什么不调用编译器生成的移动构造函数?@Gayathri如果定义副本构造函数,编译器将不会生成移动构造函数。如果您既不定义编译器也不能生成两者,或者只定义move@Ryan是的,但是我们不能确定移动构造函数是否是在两者都没有正确定义的情况下生成的?因为这取决于编译器是否能找到“有效”的副本或移动。我没弄错吗?@Gayathri我想不出任何情况下编译器可以生成一个复制ctor,但不能生成一个移动,但是如果你的类有一个只移动的数据成员,那么你可以有只移动的对象。在这种情况下,编译器无法生成副本构造函数。如果您有一个不可移动的数据成员,例如
std::mutex
,那么编译器也不能生成它。但是,如果您定义自己的复制构造函数,编译器将不会生成移动构造函数,因为它可能是wrong@Gayathri我的回答只是根据你最初的问题“为什么会这样”的简单回答;我不认为我可以在Ryan或Pradhan的评论/回答中添加更多内容,所以也可以在我用评论标记的行中为这些人添加+1:)?否,因为
a
是一个左值,异常不适用于此,因为
a
的类型为
a
,而
f
的返回类型为
B
。因此,根据C++11的规则,
a
不符合复制省略的条件。即使是编译器生成的移动构造函数,它也应该适用?对不起,我不明白你在问什么。你能说得更具体些吗?引用您所引用的行和困扰您的行为。当没有定义move和copy构造函数时,同一个return语句会发生什么情况?哪一个将被隐式调用?这是我发布的代码。谢谢@Pradhan.)我得到了它!由于用户声明了移动构造函数,因此删除了赋值运算符(用于
c=a.fun(b)
),因此无法编译此代码。它确实适合我。是否也需要定义赋值运算符?
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.
}