简体   繁体   English

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

[英]Is copy assignment operator with copy and swap idiom and self assignment check recommended?

Here you can see copy assignment operator implementation with self assignment check: 在这里,您可以看到自我分配检查的复制赋值运算符实现:

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;
}

This is good for self assignment, but bad for performance: 这对于自我分配很有用,但对性能有害:

  1. as each time it check as if statement (I don't know how much will be it optimal, considering the branch prediction) 因为每次检查就好如果声明(我不知道它会是多少最佳,考虑到分支预测)
  2. Also we lose here copy elision for rvalue arguments 我们也失去了rvalue参数的复制省略

So I still don't understand if I would implement std::vector 's operator= how I would implement it. 所以我仍然不明白我是否会实现std::vectoroperator=我将如何实现它。

Yes, this code is superflous. 是的,这段代码是超级的。 And it is true that it is causing extra unncessary branch. 确实,它正在造成额外的不必要的分支。 With proper swap and move semantics, following should be much more performant: 通过适当的交换和移动语义,以下应该更高性能:

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;
}

Also note, it is more benefical to accept the argument by value. 另请注意,按值接受参数更为有益。

as each time it check as if statement (I don't know how much will be it optimal, considering the branch prediction) 因为每次检查就好如果声明(我不知道它会是多少最佳,考虑到分支预测)

I think you've got yourself in a premature optimization circle here. 我想你在这里已经处于一个过早的优化圈。

Check for self assignment -> self-assignment is unnecessary if you wrote the code properly -> why not write swap explicitly if you mean it? 检查自我分配 - >如果正确编写代码,则不需要自我分配 - >为什么不明确地写swap -> we're back to square one - >我们回到原点

Realistically, I would just implement Allocator and not worry about it. 实际上,我只是实现Allocator而不用担心它。

Also we lose here copy elision for rvalue arguments 我们也失去了rvalue参数的复制省略

I don't think so. 我不这么认为。

#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;
}

Outputs: 输出:

default
default
copy assign
destruct
destruct

This is with -fno-elide-constructors . 这是-fno-elide-constructors


You claim the branch may be a problem, but the assembly output for -O2 shows me that GCC doesn't even emit code for the operator= and just outputs the "copy assign" string directly. 你声称分支可能有问题,但-O2的汇编输出显示GCC甚至没有为operator=发出代码,只是直接输出"copy assign"字符串。 Yes, I realized I have a simplified example, but it really is the wrong end of the pile to start from. 是的,我意识到我有一个简化的例子,但它确实是从一开始的错误结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 对派生运算符使用派生类的复制和交换习惯用法 - Using the copy and swap idiom for assignment operator with derived classes 如何在赋值运算符中使用noexcept与copy-and-swap惯用法? - How to use noexcept in assignment operator with copy-and-swap idiom? 使用复制和交换惯用法移动构造函数和赋值运算符 - move constructor and assignment operator impletemented using copy-and-swap idiom 安全分配和复制交换习语 - Safe assignment and copy-and-swap idiom 复制分配运算符=自赋值检查错误 - copy assignment operator= self-assignment check error 为什么内存泄漏仅在赋值运算符重载但不在复制构造函数中以及复制和交换习惯用法如何解析时发生 - Why memory leak only happens in case of assignment operator overloading but not in copy constructor and how copy and swap idiom resolves it 在自我分配期间,复制和交换习语是如何工作的? - How does the copy-and-swap idiom work during self-assignment? C ++移动分配可防止复制交换习惯用法 - C++ move-assignment prevents copy-swap idiom 复制和交换技术在赋值运算符函数中使用复制构造函数 - copy and swap technique uses copy constructor inside assignment operator function 检查复制构造函数中的“自赋值”? - Check for "self-assignment" in copy constructor?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM