具有移动构造函数和赋值的类的默认复制构造函数和赋值

Ale*_*x F 5 c++ move-semantics c++11

假设我有这个课程:

class Test
{
public:
    Test();
};
Run Code Online (Sandbox Code Playgroud)

AFAIK,编译器提供默认的复制构造函数和赋值运算符,它将其他实例的每个成员分配给当前实例.现在我添加移动构造函数和赋值:

class Test
{
public:
    Test();
    Test(Test&& other);
    Test& operator=(Test&& other);
};
Run Code Online (Sandbox Code Playgroud)

该类是否仍包含编译器生成的复制构造函数和赋值运算符,或者我需要实现它们?

编辑.这是我的测试:

class Test
{
public:
    Test(){}

    Test(Test&& other){}
    Test& operator=(Test&& other)
    {
        return *this;
    }

    int n;
    char str[STR_SIZE];
};

int main()
{
    Test t1;
    t1.n = 2;
    strcpy(t1.str, "12345");

    Test t2(t1);

    Test t3;
    t3 = t1;

    cout << t2.n << " " << t2.str << " " << t3.n << " " << t3.str << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印2 12345 2 12345.编译器:VC++ 2010.根据此测试,复制构造函数和赋值仍在此处.这是标准行为,我能确定这对每个C++编译器都有效吗?

jua*_*nza 7

12.8-7开始复制和移动类对象[class.copy]

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

12.8-18

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

根据这一点,由于您已声明了移动构造函数移动赋值运算符,但没有复制赋值运算符,复制构造函数或析构函数,因此您不会获得隐式生成的复制构造函数或赋值运算符.编译器为您提供声明,但声明为deleted.

以下是您的示例的简化版本:

struct Test
{
public:
    Test(){}
    Test(Test&& other){}
    Test& operator=(Test&& other) { return *this;}
};

int main()
{
  Test t1;
  Test t2(t1);
}
Run Code Online (Sandbox Code Playgroud)

以及g ++ 4.8.1产生的错误

ctors.cpp:13:13:错误:使用删除的函数'constexpr Test :: Test(const Test&)'

试验t2(t1);

ctors.cpp:1:8:注意:'constexpr Test :: Test(const Test&)'被隐式声明为已删除,因为'Test'声明了一个移动构造函数或移动赋值运算符

结构测试

(强调我的)