如果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=
的对象(或任何按值获取其参数的函数)是临时对象,则编译器可以(并且通常)根本不做任何复制。这叫做copy elision。
因此,如果rhs
是临时的,则不会进行复制。我们只剩下:
this
和rhs
内容rhs
所以路过的值是在这种情况下,不是通过引用传递更高效。
实际上,如果MyClass具有默认构造函数,则无关紧要。只有数据成员和基类有一个... – 2010-09-06 14:13:26
是的,你说得对。 – 2010-09-06 14:15:59
好的,谢谢。我这样做是为了避免代码重复执行'operator ='和拷贝构造函数。使用copy-and-swap成语,代码在复制构造函数和'swap'方法中被复制。我对吗? – gregseth 2010-09-08 07:42:41
该实现意味着所有数据成员(和基类)的默认构造函数都是可用的,并且可以从MyClass访问,因为它们将在进行赋值之前先被调用。即使在这种情况下,对构造函数进行额外的调用可能会很昂贵(取决于类的内容)。
我仍然坚持通过初始化列表单独实施复制构造函数,即使这意味着需要编写更多的代码。
另一件事:此实现可能有副作用(例如,如果您有动态分配的成员)。
如果MyClass
分配内存或可变,我会说这是不好的。
如果它不可变,那么它将不会有'operator =' - 这是一个变异函数。或者,我的意思不是像你一样可变吗? – 2010-09-06 18:11:29
根据异常安全拷贝构造函数实现operator =更合适。参见Herb Sutter的实例4,了解该技术的解释以及为什么这是一个好主意。
虽然最终结果是一样的,成员是第一默认初始化,只有后复制。
对于'昂贵'的成员,您最好使用初始化程序列表进行复制构建。
struct C {
ExpensiveType member;
C(const C& other): member(other.member) {}
};
};
是的。
个人而言,如果你的类没有指针,虽然我不会重载平等运算符或写入拷贝构造函数并让编译器为你做;它会实现一个浅拷贝,你会确定所有成员数据都被复制,而如果你重载= op;然后添加一个数据成员,然后忘记更新超载,您将遇到问题。
@Alexandre - 我不确定在赋值运算符中传递值。通过在那里调用拷贝构造函数你会得到什么好处?这是要扣紧赋值运算符吗?
P.S.我不知道如何写评论。或者可能是我不允许写评论。
好的,我编辑我的答案提供更多的细节。 – 2010-09-06 18:12:44
通常的参考文献是http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/。我仍然不相信结论总是正确的。 – 2010-09-06 18:17:22
@Steve:对于'operator =',因为无论如何您都必须复制它,所以它不会更糟。 – 2010-09-06 18:24:03
它是技术上可以,如果你有一个工作赋值操作符(复制操作符)。
但是,你应该更喜欢复制和交换,因为:
使用[复制和交换成语(http://stackoverflow.com/questions/3279543/what-is-the-copy-and-交换-成语)。 – GManNickG 2010-09-06 15:28:03
通常,复制赋值运算符将执行一些清理。如果你的类有一个指向动态分配内存的指针,复制赋值操作符应该做的第一件事是释放内存。这个拷贝构造函数的实现会给拷贝赋值操作符一个悬挂指针,而你不想删除它。 – Kevin 2014-11-08 22:40:14
即使你使用智能指针(在这种情况下删除不会有问题),你仍然会毫无意义地默认构造并分配所有的成员变量。只需使用复制和交换。 – Kevin 2014-11-08 22:43:56