Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 错误:';的重载不明确;运算符=';在swap函数中使用复制和交换习惯用法_C++_Copy And Swap_Pass By Const Reference - Fatal编程技术网

C++ 错误:';的重载不明确;运算符=';在swap函数中使用复制和交换习惯用法

C++ 错误:';的重载不明确;运算符=';在swap函数中使用复制和交换习惯用法,c++,copy-and-swap,pass-by-const-reference,C++,Copy And Swap,Pass By Const Reference,在具有常量引用作为成员的类中使用时, 出现上述错误 示例代码: #包括 #包括 使用std::reference_包装器; I类保持参考; 无效交换(I_持有参考&第一,I_持有参考&第二); I类保持参考{ 内联I_hold_reference(const int&number_reference):my_reference(number_reference){} 朋友无效交换(I_hold_reference&first,I_hold_reference&second); 内联I_保持\引用

在具有常量引用作为成员的类中使用时, 出现上述错误

示例代码:

#包括
#包括
使用std::reference_包装器;
I类保持参考;
无效交换(I_持有参考&第一,I_持有参考&第二);
I类保持参考{
内联I_hold_reference(const int&number_reference):my_reference(number_reference){}
朋友无效交换(I_hold_reference&first,I_hold_reference&second);
内联I_保持\引用和运算符=(I_保持\引用其他){
掉期(*本,其他);
归还*这个;
}
内联I_保持\引用和运算符=(I_保持\引用和其他){
掉期(*本,其他);
归还*这个;
}
私人:
参考包装我的参考;
};
无效交换(I_保持参考&第一,I_保持参考&第二){
first=I_hold_reference(second.my_reference);//错误:重载运算符“=”的使用不明确(操作数类型为“I_hold_reference”和“I_hold_reference”)
}
当复制赋值运算符被更改为通过引用而不是通过值获取其参数时,错误被修复

inline I_hold_引用和运算符=(I_hold_引用和其他){…}
为什么这会修复错误? 一个可能的含义是,链接问题中引用的内容丢失。对于推荐人来说这是真的吗? 这一变化的其他影响是什么


有一个依赖于此运算符的代码库,没有其他成员,只有提到的引用。是否需要以某种方式使代码库适应这种变化,或者它是安全的

如果仔细遵循链接的描述,您将看到必须只有一个重载
操作符=
,并且需要按值获取其参数。因此,只需删除
操作符=(I_hold_reference&&)
重载即可使代码可编译

然而,这不是唯一的问题。您的
交换
无法交换!相反,它将
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;
};
I类保持参考
{
I_保持参考(常数整数和数字参考)
:my_reference(number_reference){}
朋友无效交换(I_持有参考&第一,I_持有参考&第二)
{
使用std::swap;
交换(第一个.我的参考,第二个.我的参考);
}
I_hold_reference&运算符=(I_hold_reference other)
{
掉期(*本,其他);
归还*这个;
}
私人:
参考包装我的参考;
};
注意:我删除了不必要的
inline
s,因为成员函数是隐式内联的。我还声明了类中的
swap
函数。您可以在共享的链接中找到对此的解释


此外,在这个特定的示例中,首先不需要使用复制和交换习惯用法
std::reference_wrapper
不是手动维护的资源,这意味着它内置了正确的复制和移动语义。因此,在这个特定的示例中,编译器生成的复制和移动操作符的行为与这里手动创建的完全相同。所以,你应该使用这些,而不是以任何方式写你自己的。另一方面,如果这只是一个玩具示例,并且实际类中有更多的资源确实需要手动管理,那么这就是方法。

使用转发引用
&&
将绑定到任何右值(临时/转发引用)。这些类别也可以作为值传递,然后是不明确的。也就是说,例如,临时值是不明确的,因为左值不明确(使用值重载)


其中,非常量引用永远不能绑定到临时引用或转发引用。常量引用可以,但并不含糊。

您通常不(从不?)想要一个值重载和一个右值重载,因为它们在大多数情况下(总是?)都是含糊不清的。顺便说一下,这根本不是复制和交换的习惯用法。。。这里基本上是无限递归。您不能在交换中使用
operator=
中的
swap
operator=
。您希望您的交换能够实际执行交换。在您的例子中,swap的主体应该是
std::swap(first.my\u reference,second.my\u reference)
。类定义中的成员函数定义是隐式
内联的
。这不是一个bug,但混乱会降低可读性。交换、复制和成员类型与此无关。这与
void f(int)的情况相同;无效f(int&&);int main{f(1);}
(即同样“良好”的重载)。“如果您更改为常量引用[…]”-您应该澄清这一部分。如果用常量引用重载替换by值重载,就不会有歧义,这基本上就是我们重载
operator=(a const&)
operator=(a&&)
时经常做的事情。如果用常量引用重载替换右值重载,则会有歧义,但OP提到替换by值重载,而不是右值重载。@Holt非常感谢-我想我需要阅读有关这些重载的规则。感谢您的澄清!这就解释了歧义!哦,我犯了错误,谢谢你指出这一点!在实际代码中,我使用的不是引用包装器,而是常量引用<代码>标准::交换实际上与此不兼容,但赋值在那里有效。此外,在代码中,我使用的不是int引用,而是实际的对象(带有move赋值构造函数)。您认为这些添加的代码是有效的吗?@DavidTóth引用只能初始化,以后不能重新分配。这就是为什么
swap
不能使用它的原因。此外,任何赋值运算符都不能用于具有