C++ C++;运算符重载:没有从对象到引用的已知转换?

C++ C++;运算符重载:没有从对象到引用的已知转换?,c++,operator-overloading,C++,Operator Overloading,当我尝试编译以下代码时(g++4.6.3) 我得到了错误 /tmp/test.cxx: In function ‘A operator*(const A&, const A&)’: /tmp/test.cxx:14:20: error: no match for ‘operator*=’ in ‘(* & a) *= b’ /tmp/test.cxx:14:20: note: candidate is: /tmp/test.cxx:6:1: note: A& op

当我尝试编译以下代码时(g++4.6.3)

我得到了错误

/tmp/test.cxx: In function ‘A operator*(const A&, const A&)’:
/tmp/test.cxx:14:20: error: no match for ‘operator*=’ in ‘(* & a) *= b’
/tmp/test.cxx:14:20: note: candidate is:
/tmp/test.cxx:6:1: note: A& operator*=(A&, const A&)
/tmp/test.cxx:6:1: note:   no known conversion for argument 1 from ‘A’ to ‘A&’
这让我很困惑——从一个类到该类的引用的转换怎么可能是未知的

按以下方式更改A类声明不具有任何效力:

class A
{
public:
  A() {}
  A( const A& ) {}
};
同样的错误


我将非常感谢您对这里发生的事情的提示。

正如Lucian所说,您不能将临时对象绑定到非常量引用。编译器的期望是,对象在表达式之后将不再存在,因此修改它是没有意义的

要修复代码,请删除临时变量(使参数
常量&
操作符*=
中没有意义):


当您编写
A(A)
时,您将创建一个类型为A(右值)的临时值,并使用
A
复制构造。C++声明没有R值可以作为非const引用传递。VisualStudio对此规则有点草率,但gcc和类似的工具会强制执行它

要修复此问题,请尝试这样做(这完全相同,但您可以通过命名该变量来创建左值)。关于l-和r-值的更多信息


和我在康拉德的回答上发表的反对意见一样,都是正确的。但有时,您不需要创建的副本来执行*操作。e、 g.Vector*运算符不会使用*=来表示*“Visual Studio对此规则有点草率…”:如果您在警告级别4运行,Visual Studio会捕捉到这一点/将警告视为错误(这是明智的)。@crazyjul在Vector示例中,您不认为编译器会优化复制。如前所述,C++标准声明“……”引用非const的LV值不能绑定到rVal[[…] ]和C++2015-05工作草案,[85.3(5.2)]:“引用”应该是对非易失性const类型(即CV1应该是const)的LVC++引用,或者引用应该是RValk引用。这里的解决方案非常符合建议的设计:@Ben我需要咖啡……为了捍卫我的荣誉,我通常会在醒着的时候写这个(传递值)。简单得多。而且更优化,因为当实际参数为x值时,它可以移动。您可以通过在类的范围内声明运算符来解决此问题。然后,您的方法签名将类似于:'A operator*(const A&rhs)const;'如果你想在实现中使用复合运算符,你可以写:'return*this*=rhs'@Paranaix:No,你不能在
*this
成员函数中使用
运算符*=
,因为它会修改
*this
@BenVoigt:是的,你完全正确。我想把它写成一行,却意外地去掉了所有的魔法。诀窍是从“this”创建一个副本。例如:“A ret=*this;ret*=rhs;返回ret;'
class A
{
public:
  A() {}
  A( const A& ) {}
};
A operator*(A a, const A& b)
{
    return a *= b;
}
A operator*( A a, const A& b )
{
   return a *= b;
}