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

abr*_*ert 3 c++ assignment-operator move-semantics c++11

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

A& operator=( A other ) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

代替

A& operator=( const A&  other ) { /* ... */ }
A& operator=( const A&& other ) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*anh 6

实际上,您可以使用.实现复制和交换

A& operator=( A other ) { swap(other, *this); return *this; }
Run Code Online (Sandbox Code Playgroud)

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

除了上面的功能无法标记noexcept,移动应该轻巧,便宜,不是必需的,但它应该是轻量级的.因此,移动构造函数/赋值应该是noexcept.没有noexcept移动构造函数/赋值运算符,move_if_noexcept当容器增长时无法调用,容器将返回复制.

因此,推荐的方法是:

A& operator=( const A&  other ) {
    if (std::addressof(other) != this) {
         A(other).swap(*this); // Copy constructor may throw
    }
    return *this;
}
A& operator=( A&& other ) noexcept { // note no const here
    // we don't check self assignment because
    // an object binds to an rvalue reference it is one of two things:
    //    - A temporary.
    //    - An object the caller wants you to believe is a temporary.
    swap(other); 
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

  • 在许多情况下,像这样的复制赋值运算符将是次优的,因为当`this`可能已经具有可以重用的容量时,你正在制作`other`的无条件副本. (4认同)
  • 这个答案有误导性.首先,这种实现并不妨碍我们将复制赋值运算符声明为"noexcept".这里唯一可以抛出的是参数的复制构造函数.但如果发生这种情况,它总是发生在调用者的上下文中(!).这意味着如果`swap`是`noexcept`(应该是),你可以自由地将这个"pass-by-value"赋值声明为`noexcept`. (2认同)
  • 其次,"按价值传递"成语的整个概念是将复制/移动职责降低到班级的构造者.为了正常工作而不损失性能,该类必须正确有效地定义复制和移动构造函数.后者显然可以是"noexcept",这意味着在移动上下文中,赋值运算符的上述"pass-by-value"实现将完全无异常. (2认同)

How*_*ant 5

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

它取决于数据成员和基类A,甚至可以依赖于A的基础和成员的基础和成员.

以下是指向视频的一部分的链接,该链接演示如果A有一个vector数据成员,那么复制/交换习惯用户平均可以为复制赋值运算符节省70%的性能.这与更简单的默认任务特殊成员的方法相比较.

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

class A
{
    std::vector<int> v_;
public:
    // ...
};
Run Code Online (Sandbox Code Playgroud)

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

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