如果operator=
正确定义,可以使用以下作为复制构造函数吗?
MyClass::MyClass(MyClass const &_copy)
{
*this = _copy;
}
如果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=
(或任何通过值获取其参数的函数)是临时对象,则编译器可以(并且通常会)根本不进行任何复制。这称为复制省略。
因此,如果rhs
是临时的,则不进行复制。我们剩下:
this
和rhs
内容rhs
所以在这种情况下,按值传递比按引用传递更有效。
在异常安全的复制构造函数方面实现 operator= 更为可取。请参阅 Herb Sutter 的示例 4,了解该技术的解释以及为什么它是一个好主意。
这种实现意味着所有数据成员(和基类)的默认构造函数都可以从 MyClass 中获得和访问,因为它们将在进行赋值之前首先被调用。即使在这种情况下,对构造函数的额外调用也可能很昂贵(取决于类的内容)。
我仍然会坚持通过初始化列表单独实现复制构造函数,即使这意味着编写更多代码。
另一件事:这个实现可能有副作用(例如,如果你有动态分配的成员)。
虽然最终结果是相同的,但成员首先默认初始化,然后才复制。
对于“昂贵”的成员,您最好使用初始化列表进行复制构造。
struct C {
ExpensiveType member;
C( const C& other ): member(other.member) {}
};
};
MyClass
如果分配内存或可变, 我会说这是不行的。
是的。
就个人而言,如果您的类没有指针,尽管我不会重载等于运算符或编写复制构造函数并让编译器为您完成;它将实现一个浅拷贝,你会确定所有成员数据都被复制,而如果你重载 = op; 然后添加一个数据成员然后忘记更新重载就会有问题。
@Alexandre - 我不确定在赋值运算符中传递值。在那里调用复制构造函数有什么好处?这是要固定赋值运算符吗?
PS我不知道怎么写评论。或者可能是我不允许写评论。
如果您有一个工作分配操作符(复制操作符),这在技术上是可以的。
但是,您应该更喜欢复制和交换,因为: