空身体的重载运算符神奇地工作

Posted

技术标签:

【中文标题】空身体的重载运算符神奇地工作【英文标题】:Overloaded operator with empty body magically works 【发布时间】:2015-09-04 12:28:25 【问题描述】:

我遇到了以下奇怪的行为,我无法弄清楚发生了什么。

我有一个名为mvec 的向量类,它将实际值存储在一个数组中,还有一个类mvec_transf,它是另一个向量的转换。它存储对另一个向量的引用,以及定义转换的一元函数。可以这样使用:

mvec<int, 3>                                vec1 1, 2, 3;
mvec_transf<mvec<int, 3>, std::negate<int>> vec2 vec1, std::negate<int>();
// `vec2` contains [-1 -2 -3]

我重载了operator-,这样我就可以写auto vec2 = -vec1;,这是我当前的实现:

template <class Vec_t>
mvec_transf<Vec_t, std::negate<typename Vec_t::elem_t>>
operator- (Vec_t& v)
  /*std::out << "Hello from operator- " << std::endl;*/ 

不可思议的是,这个实现(没有主体)有效。如果我注释掉定义,我会从编译器收到 no match for operator- 错误。如果我不这样做,代码编译时会出现警告缺少返回类型未使用的变量'v'。当我运行auto vec2 = -vec1 时,vec2 实际上包含一个有效的mvec_transf&lt;..&gt; 对象,该对象具有对vec1 的正确引用。

通过添加打印语句,我可以确认重载的操作符实际上被调用了。然而,对于 print 语句,vec2 包含对垃圾的引用,而不是对 vec1 的引用。

这是怎么回事?

【问题讨论】:

【参考方案1】:

你所拥有的只是未定义的行为。来自[stmt.return]:

从函数的末尾流出相当于没有值的返回;这会在返回值的函数中导致未定义的行为。

一种未定义的行为是神奇的工作代码。另一种类型是神奇地破坏你的硬盘驱动器代码。我不会依靠它神奇地工作很长时间。修复它!

【讨论】:

别忘了nasal demons

以上是关于空身体的重载运算符神奇地工作的主要内容,如果未能解决你的问题,请参考以下文章

小于运算符不能作为成员函数重载

C#运算符重载---逐步地分析与理解

Setter不使用重载运算符

C#,多个 == 运算符重载,没有模棱两可的空值检查

C++之类和对象

C++:使用类|| 运算符重载友元