Dan*_*ica 3 c++ swap move-semantics c++11
考虑一个自定义类,X其中包含一些资源(为了简单起见,这里用整数成员变量表示),其中包含移动构造函数 (MC)、移动赋值运算符 (MAO) 和自定义交换函数:
class X {
int i_;
public:
X(int i) : i_(i) { }
X(X&& rhs) = default; // move constructor
X& operator=(X&& rhs) = default; // move assignment operator
// X& operator=(X rhs) { std::swap(i_, rhs.i_); return *this; } // unifying assign. op.
friend void swap(X& lhs, X& rhs) { std::swap(lhs.i_, rhs.i_); }
int i() const { return i_; }
};
Run Code Online (Sandbox Code Playgroud)
在以下基准代码中:
int main() {
int i1, i2;
std::cin >> i1 >> i2;
X x1(i1), x2(i2);
std::cout << x1.i() << x2.i();
swap(x1, x2);
std::cout << x1.i() << x2.i();
std::swap(x1, x2);
std::cout << x1.i() << x2.i();
}
Run Code Online (Sandbox Code Playgroud)
swap(x1, x2)只需交换 2 个整数即可。std::swap(x1, x2) 调用 1x MC 和 2x MAO。std::swap(x1, x2) 则调用 3x MC 和 2x UAO。(使用 gcc/libstdc++ 测试)。
看起来,自定义swap非常有价值,因为它避免了许多函数调用。然而,当我查看该程序的分解输出时:https://godbolt.org/g/RMfZgL,MC、MAO、UAO的所有功能swap都直接内联到std::swap(带标志的 gcc/clang )中。此外,程序中不会创建任何类型的对象,它仅适用于机器代码级别的整数。main-O2X
因此,在我看来,没有理由为swap像X.
问题:
std::swap?或者,我应该swap为所有自定义类定义自定义吗?swap真正有益?你应该遵循0的规则。
非资源管理类应该有默认的移动/复制/分配/销毁。
资源管理类应该只关心管理资源。
您的代码不管理资源。一切复制/移动都应该默认。
swap是移动的一个特例。如果您是资源管理类型,您可能也想编写它。然而,像大多数事情一样,它是一种优化,只有在证明它对性能有影响时才应该进行此类优化。
它可能会对性能产生影响的一个例子是,如果您有一个永不为空的资源拥有类型,并且该资源不是免费的,那么创建临时对象会产生不可避免的成本。 std::swap默认情况下,移动穿过一次性对象。自定义交换可以避免这种情况。
或者,一种类型,它是一个大缓冲区,可以廉价地移动元素;创建如此大的缓冲区可能会产生实际成本。
否则,不要这样做。并测试一下你是否这样做会有帮助。自定义交换是针对特定情况的移动优化。
| 归档时间: |
|
| 查看次数: |
978 次 |
| 最近记录: |