【发布时间】:2014-11-14 12:47:56
【问题描述】:
始终使用std::swap 实现我的复制赋值运算符是否是一种好的一般做法?我的理解是,这提供了一种共享复制构造函数实现的方法。我想避免复制实际的复制逻辑本身。所以这就是我要做的:
class Foo
{
public:
Foo(Foo const& other) { /* assume valid implementation */ }
Foo& operator= (Foo other)
{
std::swap(*this, other);
return *this;
}
};
将“other”传递给赋值运算符的行为执行复制构造(此时我们已经共享了复制逻辑)。我假设交换将调用移动构造(这里有一个编译器生成的实现)。
我已经对几乎每个我实现复制构造的类都这样做了,因为赋值和构造函数从来没有不同的实现。
【问题讨论】:
-
是的,复制和交换习语对于任何拥有资源的类来说都是一个很好的习语。另一个好处是您可以从交换中获得强大的异常保证。如果更多基于意见,则作为代码库的“一般规则”,imo。
-
您应该在
swap之前为using namespace std;并删除std::。这样,如果可用,将使用更具体的swap。除此之外,这是相当标准的。 -
有些人认为用
swap来实现特殊的成员函数并不是最优的。由于swap将other带入某些特定状态,因此存在一些不必要的分配。此外,提供强异常保证的赋值运算符可能是一种悲观:用户可能不需要这种保证,但无论如何他们都会为此付出代价。 -
@dyp 好点,但我认为从设计的角度来看,稍后返回并确保异常安全是一个很大的痛苦,有时如果不讨论完整的重写,你就无法做到这一点。与本地化和许多其他基础性事情一样,最好提前做好。
-
"(这里有一个编译器生成的实现)。" - 您在示例代码中阻止了编译器生成的实现。如果您打算拥有它,请添加正确的
=default