我们需要移动和复制分配吗?

时间:2016-12-01 10:17:54

标签: c++ c++11 move-semantics assignment-operator

对于课程A,我们可以使用

A& operator=( A other ) { /* ... */ }

而不是

A& operator=( const A&  other ) { /* ... */ }
A& operator=( const A&& other ) { /* ... */ }

没有恶化表现或其他负面影响?

3 个答案:

答案 0 :(得分:6)

实际上,您可以使用

实现复制和交换
RewriteRule

对于复制和移动分配,但自我赋值运算符的无条件复制将降低性能。

除了以上功能不能被标记为A& operator=( A other ) { swap(other, *this); return *this; } 移动应该是轻量级的,便宜的,它不是必需的,但它应该是轻量级的。因此,移动构造函数/赋值应为noexcept。如果没有noexcept移动构造函数/赋值运算符,则在容器增长时无法调用move_if_noexcept,容器将返回复制。

因此,推荐的方法是:

noexcept

答案 1 :(得分:5)

  

没有恶化表现或其他负面影响?

这取决于A的数据成员和基类,甚至可以取决于A的基础和成员的基础和成员。

以下链接指向视频的一部分,该视频演示如果Avector作为数据成员,那么复制/交换习惯用品可能会导致 70%的性能损失,用于平均的复制赋值运算符。这与更简单的默认任务特殊成员的方法相比较。

http://www.youtube.com/watch?v=vLinb2fgkHk&t=35m30s

class A
{
    std::vector<int> v_;
public:
    // ...
};

您可以期望string数据成员与vector数据成员具有相同的影响。

如果您不确定自己的A,并且性能对您来说很重要,请尝试两种方法并进行衡量。这正是视频中所展示的内容。

答案 2 :(得分:4)

  • “移动”环境的表现可能会受到轻微影响。

    如果您的类A是可移动的,那么在移动上下文中,按值传递的复制和交换实现将按两个操作的顺序实现移动:

    1. 使用other的移动构造函数将右侧(RHS)值移动到参数A
    2. 将数据从other移至*this(或与other交换*this
    3. 第二个实现(使用专门的移动分配)可以在一个操作中执行相同的操作:它将直接使用*this移动(或交换)右侧值。

      因此,可能,复制和交换变体涉及额外移动的开销。

    4. “复制”环境的表现可能会受到轻微到严重的影响。

      如果您的左侧(LHS)有一些可复制的内部资源(如内存块),可以容纳相应的RHS值而无需重新分配,那么专用的复制分配实现只需要从RHS资源复制数据到LHS资源。不需要内存分配。

      在copy-and-swap变体中,无条件地创建副本,并且必须无条件地分配和释放上述内部资源。这会对性能产生重大负面影响。