3

I saw a sentence in The C++ programing language which I'm confused with:

• If the programmer declares a copy operation, a move operation, or a destructor for a class,no copy operation, move operation, or destructor is generated for that class.

I wrote a test code shown below:

#include <iostream>
using namespace std;
class A
{
public:
    A() :a(0){}
    A(int _a) :a(_a){}
    int get() const
    {
        return a;
    }
    /*A& operator=(const A &x)
    {
        a = x.a;
        cout << "A copy assignment" << endl;
        return *this;
    }*/
    A& operator=(A&&x)
    {
        cout << "A move assignment" << endl;
        swap(a, x.a); 
        return *this;
    }
private:
    int a;
};

A operator+(const A &x, const A &y)
{
    A temp{ x.get() + y.get() };
    return temp;
}

int main() 
{
    A a1(1), a2(2), a3;
    a3 = a1;
    cout << a3.get() << endl;
    return 0;
}

The result is: enter image description here

I define a move assignment, there should be not default copy assignment generated as said in the book, but how could a3 gets the copy of a1?

Another question:

I modified a3 assignment expression:

a3 = a1+a2;

the result is: enter image description here

Then I comment out the move assignment and remove comment on copy assignment:

A& operator=(const A &x)
{
    a = x.a;
    cout << "A copy assignment" << endl;
    return *this;
}
/*
A& operator=(A&&x)
{
    cout << "A move assignment" << endl;
    swap(a, x.a); 
    return *this;
}*/

the result is: enter image description here

how could copy assignment be called? The result of a1+a2 is a rvalue, how could this rvalue be passed to copy assignment whose argument is const A&? Forgive my confusion about rvalue

any help is appreciated!

4

3 回答 3

3

我定义了一个移动分配,不应该像书中所说的那样生成默认的复制分配

正确的。

但是 a3 怎么能得到 a1 的副本呢?

它不能按照标准。如果编译器没有为此提供诊断消息,则编译器不符合标准。


的结果a1+a2是一个右值

正确的。

这个右值如何传递给参数为的副本赋值const A&

因为 rvalues 可以绑定到对const. 临时对象的生命周期被延长以匹配引用的潜在生命周期。在引用参数的情况下,这是函数的持续时间。

于 2017-05-18T13:40:36.160 回答
0

基于对 GCC 6 的一些实际实验和那个(有点令人困惑的)句子,这就是我发现的:

  • 如果为类声明任何其他构造函数,则不会定义默认构造函数。
  • 如果您声明一个复制操作(构造函数或赋值运算符),则会隐式生成另一个复制操作。但是,这一代已被 ISO 标准弃用,如书中句子后面的段落中所述。
  • 如果声明析构函数,则会隐式生成复制操作。这也被弃用了。
  • 如果您声明复制操作,则移动操作将被隐式删除(默认为复制操作,如下所示)。
  • 如果您声明一个移动操作,则另一个移动操作将被隐式删除。
  • 如果您声明一个移动操作,复制操作将被隐式删除。
  • 如果您声明析构函数,则任何使用隐式移动操作的代码都会使用隐式复制操作(或显式复制操作,如果已定义)。但是,这可能会从上面学到的内容中被隐含地弃用。
  • 如果未定义显式析构函数,则似乎总是为类生成默认(空)析构函数,无论已定义或未定义哪些其他操作。
于 2019-01-28T10:29:59.907 回答
0

该声明具有前瞻性和简洁性。它还没有完全实现 C++ 11 标准,但它迟早会到来。

C++11 标准第 12.8.7 节引用:

如果类定义没有显式声明复制构造函数,则隐式声明。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数定义为已删除;否则,它被定义为默认(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。

于 2022-01-05T14:57:23.717 回答