繁体   English   中英

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

[英]Implementing the copy constructor in terms of operator=

如果正确定义了operator= ,可以使用以下作为复制构造函数吗?

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

如果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=的对象(或任何通过value获取其参数的函数)是一个临时对象 ,编译器可以(并且通常)根本不进行复制。 这称为复制省略

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

  • 交换thisrhs内容
  • 消灭rhs

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

根据异常安全拷贝构造函数,更可取的是实现operator =。 参见Herb Sutter的实施例4.对该技术的解释以及为什么这是一个好主意。

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

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

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

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

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

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

struct C {
   ExpensiveType member;

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



 };

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

是。

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

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

PS我不知道怎么写评论。 或者可能是我不允许写评论。

技术上好的,如果你有一个工作的赋值运算符(拷贝操作)。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM