复制赋值运算符是否建议使用复制和交换习惯用法以及自我分配检查?

时间:2016-05-09 20:49:43

标签: c++ c++11 stdvector copy-assignment

Here您可以通过自行分配检查看到复制赋值运算符实现:

String & operator=(const String & s)
{
    if (this != &s)
    {
        String(s).swap(*this); //Copy-constructor and non-throwing swap
    }

    // Old resources are released with the destruction of the temporary above
    return *this;
}

这对自我分配有好处,但对性能不利:

  1. 每次检查时都好像是声明(考虑到分支预测,我不知道它会有多大优化)
  2. 此外,我们在这里失去了rvalue参数的复制省略
  3. 所以我仍然不明白我是否会实施std::vector operator=我将如何实施它。

2 个答案:

答案 0 :(得分:5)

是的,这段代码非常棒。确实,它正在造成额外的不必要的分支。通过适当的交换和移动语义,以下应该更高效:

String& String::operator=(String s) { // note passing by value!

    std::swap(s, *this); // expected to juggle couple of pointers, will do nothing for self-assingment
    return *this;
}

另请注意,按值接受参数更为有益。

答案 1 :(得分:1)

  

每次检查时都是if语句(考虑到分支预测,我不知道它会有多大优化)

我认为你在这里已经处于一个过早的优化圈。

检查自我分配 - >如果您正确编写代码,则无需自行分配 - >如果你的意思,为什么不明确地写swap? - >我们回到了原点

实际上,我只会实施Allocator而不用担心。

  

此外,我们在这里失去了rvalue参数的复制省略

我不这么认为。

#include <iostream>

#define loud(x) std::cout << x << "\n";

struct foo
{
    foo() { loud("default") }
    ~foo() { loud("destruct") }

    foo(const foo&) { loud("copy") }
    foo(foo&&) { loud("move") }

    foo & operator=(const foo & s)
    {
        if (this != &s)
        {
            loud("copy assign")
        }

        return *this;
    }
};

int main()
{
    foo f;
    foo g;
    g = f;
}

输出:

default
default
copy assign
destruct
destruct

这是-fno-elide-constructors

您声称分支可能有问题,但-O2的汇编输出显示GCC甚至没有为operator=发出代码,只是直接输出"copy assign"字符串。是的,我意识到我有一个简化的例子,但真的是错误的开始。