【问题标题】:C++: autogenerated(default) copy costructorC++:自动生成(默认)复制构造函数
【发布时间】:2013-01-23 03:09:07
【问题描述】:

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

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

所以这里不需要

【问题讨论】:

  • 您是否将 copy-constructorcopy-assignment 运算符混淆了?
  • 不,复制赋值操作符是operator=(),复制构造函数是A::A(A&);
  • 我明白了,当需要一个副本作为other operator= 的参数时,会调用复制构造函数
  • 你可能想要A& operator=(const& A); 而不是A& operator=(const A);,它们是非常不同的东西。

标签: c++ operator-overloading copy-constructor


【解决方案1】:
A::A(const A& other) != A& A::operator=(const A other)

【讨论】:

    【解决方案2】:

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

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

    那么您可能需要提供所有三个。此规则称为 Rule of Three


    不声明复制构造函数安全吗?

    很安全。

    您的示例案例是否必须这样做?

    不是真的。具体来说,三法则支配着这一点。有关详细信息,请查看链接的问题。


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

    我猜这是在问,默认的复制构造函数是做什么的。
    答案在:
    C++03 标准 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,但我认为这不足以回答这个问题。这显然很重要,但我认为问题包括“我什么时候必须提供三个中的任何?没有动态内存或指针足以证明我不需要任何东西吗?”。
    • @us2012:更新为更具体。 Hth.
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您似乎将 copy-constructorscopy-assignment 运算符混淆了。隐式生成的 copy-constructorcopy-construct 每个成员:

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

      隐式生成的copy-assignment操作符会copy-assign每个成员:

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

      您在问题中定义的 copy-assignment 运算符采用 copyA,因此 copy-constructor 将被调用以创建传递给operator= 的参数。请注意,在某些情况下可能会省略副本。

      【讨论】:

        猜你喜欢
        • 2016-12-16
        • 2020-05-14
        • 1970-01-01
        • 2013-03-16
        • 1970-01-01
        • 2012-03-08
        • 2016-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多