如果我声明一个类,(没有动态内存分配,没有指针):
class A{
int a,b;
public:
A();
A(int,int);
A& operator=(const A);
};
不申报复制构造函数是否安全?默认的复制构造函数如何?
A& A::operator=(const A other)
{
a=other.a;
b=other.b;
return *this;
}
即使我没有宣布复制构造函数,当我调用 operator =()
时,也会调用默认值。编辑:
默认的析构函数是:
A::~A(){}
所以这里不需要
答案 0 :(得分:6)
规则是,如果您需要提供:
然后你可能需要提供所有这三个。此规则称为 Rule of Three 。
我可以安全地不申报复制构造函数吗?
很安全。
您是否需要针对您的示例案例?
不是真的。具体而言,三个人的统治就是这样。查看链接的问题以获取更多详细信息。
默认的复制构造函数如何?
我想知道,默认的复制构造函数是做什么的
答案如下:
C ++ 03 Standard 12.8复制类对象:
第8段:
X类的隐式定义的复制构造函数执行其子对象的成员复制。复制的顺序与用户定义的构造函数中基数和成员的初始化顺序相同(见12.6.2)。每个子对象都以适合其类型的方式复制:
- 如果子对象是类类型,则使用该类的复制构造函数;
- 如果子对象是一个数组,则以适合于元素类型的方式复制每个元素;
- 如果子对象是标量类型,则使用内置赋值运算符 虚拟基类子对象只能由隐式定义的复制构造函数复制一次(见12.6.2)。
即使我没有宣布复制构造函数,我也会在调用
时调用默认构建函数operator=()
仅在需要创建类对象的副本时才调用复制构造函数。这涉及传递给函数或从函数返回时创建的对象的副本
您的复制赋值运算符按值传递对象A
,这个传递值是通过将对象的副本传递给复制构造函数并因此调用复制构造函数来实现的。
要避免副本,您需要通过引用传递 :
A& A::operator=(const A& other)
好读:
What's the difference between passing by reference vs. passing by value?
答案 1 :(得分:3)
您似乎将 copy-constructors 与 copy-assignment 运算符混淆。隐式生成的 copy-constructor 将 copy-construct 每个成员:
A::A( A const& source )
: a( source.a )
, b( source.b )
{}
隐式生成的副本分配运算符将 copy-assign 每个成员:
A& A::operator =( A const& source )
{
a = source.a;
b = source.b;
return *this;
}
您在问题中定义的复制分配运算符需要A
个副本,因此复制构造函数将调用以创建传递给operator=
的参数。请注意,在某些情况下可能会删除副本。
答案 2 :(得分:1)
A::A(const A& other) != A& A::operator=(const A other)
答案 3 :(得分:1)
您的课程提供operator=
。根据三条规则(如@AlokSave所说),您应该提供复制构造函数和析构函数。
问题是,如果您对默认提供的复制构造函数感到满意,为什么不满意默认提供的复制赋值运算符?如果你是,那就不要声明operator=
并让编译器为你生成整个“三规则”。