复制赋值运算符应该通过 const 引用还是按值传递?

Posted

技术标签:

【中文标题】复制赋值运算符应该通过 const 引用还是按值传递?【英文标题】:Should copy assignment operator pass by const reference or by value? 【发布时间】:2016-12-13 00:09:38 【问题描述】:

在 C++11 之前,复制赋值运算符始终应通过 const 引用传递,如下所示:

template <typename T>
ArrayStack<T>& operator= (const ArrayStack& other);

然而,随着移动赋值运算符和构造函数的引入,似乎有些人提倡使用按值传递来代替复制赋值。还需要添加一个移动赋值运算符:

template <typename T>
ArrayStack<T>& operator= (ArrayStack other);
ArrayStack<T>& operator= (ArrayStack&& other);

上面2个算子的实现是这样的:

template <typename T>
ArrayStack<T>& ArrayStack<T>::operator =(ArrayStack other)

    ArrayStack tmp(other);
    swap(*this, tmp);
    return *this;


template <typename T>
ArrayStack<T>& ArrayStack<T>::operator =(ArrayStack&& other)

    swap(*this, other);
    return *this;

在为 C++11 以后创建复制赋值运算符时使用按值传递是个好主意吗?什么情况下应该这样做?

【问题讨论】:

operator=(ArrayStack) 没有理由创建副本tmp slideshare.net/ripplelabs/howard-hinnant-accu2014 幻灯片 43-53 按值传递的版本可以同时进行移动和复制赋值,通常通过复制和交换。 【参考方案1】:

在 C++11 之前,复制赋值运算符总是应该通过 const 引用传递

这不是真的。最好的方法一直是使用the copy-and-swap idiom,这就是您在这里看到的(尽管正文中的实现不是最佳的)。

如果有的话,这 less 在 C++11 中很有用,因为你也有一个移动赋值运算符。

【讨论】:

所以我猜什么都没有改变,通过 const 引用提供复制赋值运算符和移动赋值运算符仍然是标准的吗? @Mantracker:您应该阅读链接的答案。实际上,您也应该阅读此答案,基于您的陈述 “通过 const 引用提供复制赋值运算符仍然是标准的” 这与我所说的直接矛盾。 我明白了,如果我没记错的话,上次我读到这个答案时,它并没有用 C++ 11 更新。或者我没有完全理解,谁知道呢 @Mantracker:这并不重要,因为正如我现在多次说过的那样,即使在 C++03 中你也错了。 @kfsone:这是 C++11 常见问题解答,而不是 C++03 常见问题解答。我已经说过复制和交换在 C++11 中没有那么有用,所以也许这就是原因。但是,无论哪种方式,断言 Bjarne 或标准库接口都是良好的、广泛建立的约定的全部和全部都是荒谬的。

以上是关于复制赋值运算符应该通过 const 引用还是按值传递?的主要内容,如果未能解决你的问题,请参考以下文章

按值传递结果

何时重载按引用传递(左值和右值)优于按值传递?

按值返回和通过 const 引用传递时避免临时构造

为啥向量被视为按值传递,即使它是通过 const 引用传递的?

按值传递时“const”不是多余的吗? [复制]

Swift 函数是按值还是按引用分配/传递?