2

如果我声明一个类,(没有动态内存分配,没有指针):

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(){}

所以这里不需要

4

4 回答 4

6

规则是,如果您需要提供:

  • 复制构造函数或
  • 析构函数或
  • 复制赋值运算符

那么您可能需要提供所有三个。这条规则被称为三规则


声明复制构造函数是否安全?

这是安全的。

您是否必须为您的示例案例?

并不真地。具体来说,三法则支配着这一点。检查链接的问题以获取更多详细信息。


默认的复制构造函数是什么样子的?

我认为这是在问,默认的复制构造函数是做什么的。
答案在:
C++03 标准 12.8 复制类对象:
第 8 段:

类 X 的隐式定义的复制构造函数执行其子对象的成员复制。复制的顺序与用户定义的构造函数中基和成员的初始化顺序相同(见 12.6.2)。每个子对象都以适合其类型的方式复制:

— 如果子对象是类类型,则使用该类的复制构造函数;
— 如果子对象是一个数组,则以适合元素类型的方式复制每个元素;
— 如果子对象是标量类型,则使用内置赋值运算符。
虚拟基类子对象只能由隐式定义的复制构造函数复制一次(见 12.6.2)。


即使我不声明复制构造函数,调用时也会调用默认的构造函数operator=()

仅当需要创建类对象的副本时才调用复制构造函数。这涉及在传递到函数或从函数返回时创建的对象的副本。
您的复制赋值运算符A 按值传递对象,这种按值传递是通过通过复制构造函数传递对象的副本并因此调用复制构造函数来实现的。
为避免复制,您需要通过引用传递:

A& A::operator=(const A& other)

好读:
按引用传递与按值传递有什么区别?

于 2013-02-07T15:01:07.590 回答
3

您似乎将复制构造函数复制赋值运算符混淆了。隐式生成的复制构造函数复制构造每个成员:

A::A( A const& source )
  : a( source.a )
  , b( source.b )
{}

隐式生成的复制赋值运算符将对每个成员进行复制赋值:

A& A::operator =( A const& source )
{
    a = source.a;
    b = source.b;
    return *this;
}

您在问题中定义的复制赋值A运算符采用by copy,因此将调用复制构造函数operator=来创建传递给的参数。请注意,在某些情况下可能会省略副本。

于 2013-02-07T15:01:45.437 回答
1
A::A(const A& other) != A& A::operator=(const A other)
于 2013-02-07T15:02:16.137 回答
1

您的班级提供operator=. 根据三个规则(如@AlokSave 所说),您还应该提供复制构造函数和析构函数。

问题是,如果您对默认提供的复制构造函数感到满意,为什么您对默认提供的复制赋值运算符不满意?如果您是,请不要声明operator=并让编译器为您生成整个“三规则”。

于 2013-02-07T15:07:04.333 回答