根据operator =实现复制构造函数

时间:2010-09-06 14:07:38

标签: c++ copy-constructor

如果operator=已正确定义,是否可以将以下内容用作复制构造函数?

MyClass::MyClass(MyClass const &_copy)
{
    *this = _copy;
}

8 个答案:

答案 0 :(得分:27)

如果MyClass的所有成员都有默认构造函数,那么。

请注意,通常是相反的方式:

class MyClass
{
public:
    MyClass(MyClass const&);     // Implemented
    void swap(MyClass&) throw(); // Implemented
    MyClass& operator=(MyClass rhs) { rhs.swap(*this); return *this; }
};

我们在operator=中传递值,以便调用复制构造函数。请注意,一切都是异常安全的,因为swap保证不会抛出(您必须在实现中确保这一点)。

根据要求编辑有关按值调用的内容:operator=可以写为

MyClass& MyClass::operator=(MyClass const& rhs)
{
    MyClass tmp(rhs);
    tmp.swap(*this);
    return *this;
}

通常会告诉C ++学生通过引用传递类实例,因为如果通过值传递复制构造函数,则会调用它。在我们的例子中,无论如何我们必须复制rhs,所以按值传递是合适的。

因此,operator=(第一个版本,按值调用)读取:

  • 复制rhs(通过复制构造函数,自动调用)
  • *this
  • 交换其内容
  • 返回*this并让方法退出时销毁rhs(包含旧值)。

现在,我们通过这个按值调用获得额外奖励。如果传递给operator=的对象(或通过值获取其参数的任何函数)是临时对象,则编译器可以(并且通常)根本不进行复制。这称为 copy elision

因此,如果rhs是临时的,则不会复制。我们留下:

  • 交换thisrhs内容
  • 摧毁rhs

因此,在这种情况下,通过值传递 more 比通过引用传递更有效。

答案 1 :(得分:11)

建议在异常安全拷贝构造函数方面实现operator =。参见Herb Sutter的例子4.这个技术的解释以及为什么这是一个好主意。

http://www.gotw.ca/gotw/059.htm

答案 2 :(得分:5)

此实现意味着所有数据成员(和基类)的默认构造函数都可以从MyClass中访问和访问,因为在进行赋值之前将首先调用它们。即使在这种情况下,对构造函数进行额外调用也可能很昂贵(取决于类的内容)。

我仍然坚持通过初始化列表单独实现复制构造函数,即使这意味着编写更多代码。

另一件事:此实现可能有副作用(例如,如果您有动态分配的成员)。

答案 3 :(得分:1)

虽然最终结果相同,但成员首先默认初始化,之后才复制。

使用“昂贵”成员,您最好使用初始化列表进行复制构建。

struct C {
   ExpensiveType member;

   C( const C& other ): member(other.member) {}
};



 };

答案 4 :(得分:0)

如果MyClass分配内存或可变,我会说这不行。

答案 5 :(得分:0)

就个人而言,如果你的类没有指针,虽然我不会重载相等的运算符或编写复制构造函数,让编译器为你做;它将实现一个浅拷贝,你肯定会知道所有成员数据都被复制了,而如果你重载了= op;然后添加一个数据成员,然后忘记更新你遇到问题的重载。

答案 6 :(得分:0)

@Alexandre - 我不确定在赋值运算符中传递值。通过在那里调用复制构造函数可以获得什么优势?这是否会固定赋值运算符?

P.S。我不知道如何写评论。或者可能是我不允许写评论。

答案 7 :(得分:0)

如果你有一个工作任务操作员(复制操作员), 在技术上是正常的。

但是,您应该更喜欢复制和交换,因为:

  • 使用copy-swap轻松实现异常安全
  • 最关注的逻辑分离
    • copy-ctor是关于分配所需的资源(复制其他内容)。
    • 交换功能(主要)关于交换内部“句柄”,不需要进行资源(de)分配
    • 析构函数是关于资源释放
    • 复制和交换自然地将这三个功能组合在赋值/复制操作符