假设我有这门课程:
class Test
{
public:
Test();
};
AFAIK,编译器提供默认的复制构造函数和赋值运算符,它将其他实例的每个成员分配给当前实例。现在我添加移动构造函数和赋值:
class Test
{
public:
Test();
Test(Test&& other);
Test& operator=(Test&& other);
};
此类是否仍包含编译器生成的复制构造函数和赋值运算符,或者我需要实现它们?
修改即可。这是我的考验:
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;
}
打印2 12345 2 12345
。编译器:VC ++ 2010.根据此测试,复制构造函数和赋值仍在此处。这是标准行为,我能确定这对每个C ++编译器都有效吗?
答案 0 :(得分: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);
}
g ++ 4.8.1产生的错误
ctors.cpp:13:13:错误:使用已删除的函数'constexpr Test :: Test(const Test&amp;)'
测试t2(t1);
ctors.cpp:1:8:注意:'constexpr Test :: Test(const Test&amp;)'被隐式声明为已删除的,因为'Test'声明了一个移动构造函数或移动赋值运算符 < / p>
struct Test
(强调我的)
答案 1 :(得分:1)
根据第12.8节复制和移动C ++标准的类对象
7如果类定义没有明确声明副本 构造函数,一个是隐式声明的。如果是类定义 声明一个移动构造函数或移动赋值运算符 隐式声明的复制构造函数被定义为已删除;除此以外, 它定义为默认值(8.4)。
18如果类定义没有明确声明副本 赋值运算符,一个是隐式声明的。如果上课 definition声明一个move构造函数或移动赋值运算符, 隐式声明的复制赋值运算符定义为 删除;否则,它被定义为默认值(8.4)。
因此,在您的情况下,复制构造函数和复制赋值运算符由编译器隐式声明,但定义为已删除。