在什么情况下,运算符=应该用左值/右值重载而不是复制和交换来实现
Under what situations should operator= be implemented with lvalue/rvalue overloads instead of with copy-and-swap?
正如 https://stackoverflow.com/a/3279550/943619 所描述的那样,实现operator=
的正确方法通常是:
my_type& operator=(my_type other) {
swap(*this, other);
return *this;
}
friend void swap(my_type& lhs, my_type& rhs) { ... } // This can vary some.
然而,Howard Hinnant 指出,通过为左值和右值参数实现单独的重载,有时可以做得更好:
my_type& operator=(const my_type& other) { ... }
my_type& operator=(my_type&& other) { ... }
显然,2-过载解决方案可以在几种情况下节省一次移动,但如此小的改进不太可能出现在基准测试中。相反,我正在寻找编写 2 个重载可以 ~使性能加倍的情况。
"复制和交换"成语的主要问题是效率较低。
即使我们有一个很好的swap
实现,我们仍然同时有 3 个类实例,而左值和右值运算符的另一个解决方案只有 2 个实例。
这意味着复制和交换所需的内存增加了 50%,并且还可能产生大量时间成本 - 因为您必须获取原本不需要的资源。
考虑std::vector
情况:如果您执行vec1=vec2;
并且两者都具有相同的大小,请使用左值引用 - 您根本不需要执行任何new
和delete
。在复制和交换中,您必须创建第三个向量 - 因此您有一个额外的new
和delete
,可能需要大量时间(如果向量很小,则很重要)或大量内存(如果向量很大)
复制和交换的主要优点是异常安全。 复制和交换为您提供了强大的异常安全性,但代价是性能。
如果您需要异常安全 - 使用它。如果您需要性能(内存、时间、类获取的任何其他资源),请不要使用它。
相关文章:
- C++指针复制重载
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- C++复制函数重载导致"must be a nonstatic member function"错误
- 在 c++ 中使用深度复制的运算符重载
- 如果我也使用复制构造函数并且重载 = 运算符,我是否需要析构函数?
- 在c++中重载复制赋值运算符
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 使用继承的指针列表复制构造函数或重载运算符=
- 运算符重载C++、(+、-、*、/ 等)有没有比复制、替换和粘贴更聪明的方法?
- 重载赋值运算符函数和复制构造函数中的错误
- 复制构造函数和重载加法运算符
- 父类有 26 个构造函数重载.如何在不复制+粘贴 26 个重载的情况下将一个小任务附加到所有构造器?
- 错误消息:使用复制构造函数和重载赋值运算符
- 在复制构造函数中放入什么 = 运算符重载
- 重载分辨率:是否首选直接转换运算符(由于复制省略)?
- 重载复制赋值运算符
- 在C++中重载复制构造函数
- 从重载复制构造函数内部调用默认复制构造函数
- 我可以用重载复制继承吗?
- 重载运算符=和重载复制构造函数之间的区别是什么