C ++:赋值运算符:按值传递(复制和交换)与按引用传递

时间:2020-05-03 12:35:10

标签: c++

考虑到copy-and-swap idiom的优势...

为什么我们仍然需要接受引用作为主流的副本分配运算符?

class T {
public:

    // 1: Why still commonly this?
    T& operator=(const T& rhs);

    // 2: Why not mostly that?
    T& operator=(T rhs);
}

有答案建议使用后者(herehere)。

但是,大多数SO示例仍在通过引用传递operator=周围。

甚至是合并的C ++常见问题解答points out(是,关于const,但...):

class Fred的副本构造函数和赋值运算符应在参数中分别使用constFred::Fred(const Fred&)Fred& Fred::operator=(const Fred&)

很显然,复制和交换可以通过引用传递来实现-如果仍然要进行复制,则完全没有必要。也许还希望避免在通话时立即复制(在主体中有条件地执行复制)-难道不是那么不常见的情况(可能是过早的优化)吗?

默认情况下,不是将复制和交换与传递值分配一起使用吗?

3 个答案:

答案 0 :(得分:2)

按引用传递用于避免在需要更快的执行时不必要的复制,而const引用则用于当您希望快速且只读地传递它时。通过复制是指您要复制对象以便能够在函数的执行/实现过程中对其进行操作。

答案 1 :(得分:1)

第二种选择可能会在每个类上都不起作用,因为它可能会删除副本。

第一个选项具有很多(即使不是全部)优点:没有副本,只读语义,始终可用。

答案 2 :(得分:1)

有人指出了我宝贵的hint

例如,曾经想知道为什么高性能/经常使用的std::vectorstd::string之类的std :: types不使用复制/交换吗? | Howard Hinnant

我发现所有关于交换复制的内容都是关于优化的(避免复制,重新使用lhs):

  • 很明显,自我分配是没有问题的。
  • lhs可以容纳rhs的空间时,(STL)容器中会发生另一种常见的可能性:

    class container<T> {
    public:
        // If passed by value, created copy would unconditionally increase capacity:
        T& operator=(const container<T>& rhs) {
           // ...
           if (this->capacity() >= rhs.size()) {
               // reuse capacity ...
           } else {
               // increase capacity ...
           }
        }
    }
    

    请注意,提示还提到(STL)容器

operator=的权衡是:

  • 按值+复制和交换:具有强大的异常保证,简化了(节省人工)
  • 参考::允许优化(节省机器时间)可能会削弱保证的情况

相关答案: