在将常量引用作为成员的类中使用复制和交换惯用法时,会发生上述错误。
示例代码:
#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')
}
当将“复制”赋值运算符更改为按引用而不是按值接受其参数时,该错误已修复。
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
不是手动维护的资源,这意味着它具有适当的内置复制和移动语义。因此,在此特定示例中,编译器生成的复制和移动运算符将具有与此处手动创建的行为完全相同的行为。因此,您应该使用这些而不是以任何方式编写自己的。另一方面,如果这只是一个玩具示例,并且实际类中有更多资源需要手动管理,那么这就是要走的路。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句