错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
error: ambiguous overload for 'operator=' in swap function using the copy-and-swap idiom
在具有常量引用作为成员的类中使用复制和交换习惯用法时,出现上述错误。
示例代码:
#include <iostream>
#include <functional>
using std::reference_wrapper;
class I_hold_reference;
void swap(I_hold_reference& first, I_hold_reference& second);
class I_hold_reference{
inline I_hold_reference(const int& number_reference) : my_reference(number_reference){}
friend void swap(I_hold_reference& first, I_hold_reference& second);
inline I_hold_reference& operator=(I_hold_reference other){
swap(*this, other);
return *this;
}
inline I_hold_reference& operator=(I_hold_reference&& other){
swap(*this, other);
return *this;
}
private:
reference_wrapper<const int> my_reference;
};
void swap(I_hold_reference& first, I_hold_reference& second){
first = I_hold_reference(second.my_reference); //error: use of overloaded operator '=' is ambiguous (with operand types 'I_hold_reference' and 'I_hold_reference')
}
当Copy赋值运算符被更改为通过引用而不是通过值来获取其参数时,错误就会得到修复。
inline I_hold_reference& operator=(I_hold_reference& other){ ... }
为什么这样可以修复错误?一个可能的含义是,链接问题中引用的重要优化可能性丢失。参考资料是这样的吗?这一变化的其他含义是什么?
有一个依赖于这个运算符的代码库,没有其他成员,只有提到的引用。是否需要以某种方式调整代码库以适应这种变化,或者它是安全的?
如果您仔细遵循链接的描述,您将看到您必须只有一个operator=
重载,并且该重载需要按值获取其参数。因此,简单地删除operator=(I_hold_reference&&)
重载就会使代码变得可编译。
然而,这并不是唯一的问题。你的swap
不会交换!相反,它将second
的副本分配给first
,并保持second
不变。
这就是你想要的:
class I_hold_reference
{
I_hold_reference(const int& number_reference)
: my_reference(number_reference){}
friend void swap(I_hold_reference& first, I_hold_reference& second)
{
using std::swap;
swap(first.my_reference, second.my_reference);
}
I_hold_reference& operator=(I_hold_reference other)
{
swap(*this, other);
return *this;
}
private:
reference_wrapper<const int> my_reference;
};
注意:我删除了不必要的inline
,因为成员函数是隐式内联的。此外,我还在类中声明了swap
函数。你可以在你分享的链接中找到对此的解释。
此外,在这个特定的示例中,首先不需要使用复制和交换习惯用法。std::reference_wrapper
不是一个手动维护的资源,这意味着它内置了正确的复制和移动语义。因此,在这个特定的示例中,编译器生成的复制和移运算符将具有与此处手动创建的运算符完全相同的行为。所以,你应该使用这些,而不是以任何方式写你自己的。另一方面,如果这只是一个玩具示例,并且实际类中有更多的资源需要手动管理,那么这就是我们要走的路。
使用转发引用&&
将绑定到任何右值(临时/转发引用(。这些类别也可以作为值传递,然后是不明确的。也就是说,例如,临时是不明确的,因为左值不会是(使用值重载(。
其中,作为非常量引用,永远不能绑定到临时或转发引用。常量引用可以,但并不含糊。
- 交换函数不是在 C++ 中交换 2D 数组的元素
- 选择排序时交换函数调用的数量和完成的交换次数是否相同?
- 在C++中使用 4 个交换函数修复程序
- 如何使用Struct打印交换函数
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 从递归向后选择排序函数调用 max 和交换函数
- 使用通用交换函数来缩短代码
- 快速排序中的交换函数给出错误的输出
- 为什么每个STL容器都具有将其定义为成员函数的交换函数
- 使用交换函数交换元素是可以的吗?
- 传递参数、参数、交换函数和随机数生成器
- 如何在这个交换函数(一个单独的链表)中找到错误
- 左值和右值引用的交换函数
- 使用指针的交换函数
- 排序算法的交换函数不适用于排序函数中的参数。
- 为什么使用std::swap不会在外部范围中隐藏其他交换函数
- 交换对象不实现移动语义时的交换函数
- 我如何制作constexpr交换函数
- 在c++中编写交换函数以重新分配结构数组中的成员值
- std::排序和自定义交换函数