如果operator=
已正确定义,是否可以将以下内容用作复制构造函数?
MyClass::MyClass(MyClass const &_copy)
{
*this = _copy;
}
答案 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
是临时的,则不会复制。我们留下:
this
和rhs
内容rhs
因此,在这种情况下,通过值传递 more 比通过引用传递更有效。
答案 1 :(得分:11)
建议在异常安全拷贝构造函数方面实现operator =。参见Herb Sutter的例子4.这个技术的解释以及为什么这是一个好主意。
答案 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)
如果你有一个工作任务操作员(复制操作员), 在技术上是正常的。
但是,您应该更喜欢复制和交换,因为: