重载没有返回语句的赋值操作符

Overloading assignment operator without return statement

本文关键字:赋值操作符 语句 返回 重载      更新时间:2023-10-16

为什么允许赋值操作符返回void?为什么赋值链在这种情况下有效?看一下代码,你就会很清楚我在说什么了。

代码:

struct Foo
{
   std::string str;
   Foo(const std::string& _str)
   : str(_str)
   {
   }
   Foo& operator=(const Foo& _foo)
   {    
      str = _foo.str;
      //return *this; /* NO RETURN! */
   }
};
int main()
{
   Foo f1("1");
   Foo f2("2");
   Foo f3("3");
   f1 = f2 = f3 = Foo("4");
   std::cout << "f1: " << f1.str << std::endl;
   std::cout << "f2: " << f2.str << std::endl;
   std::cout << "f3: " << f3.str << std::endl;
   return 0;
}

问题:

    为什么这是合法的?(为什么它会编译)
  1. 为什么它工作?

我在很多地方读到"赋值操作符应该返回*这个,这样你就可以有赋值链",这完全有意义,但是为什么上面的工作?

试一试:
使用上面代码的在线c++工作空间

为什么这合法?(为什么它可以编译)

这是不合法的,并且在你的程序中注入了未定义行为。你的编译器至少应该警告你(我相信它会,如果你设置了一个足够高的警告级别)。

根据c++ 11标准第6.6.3/2段:

从函数末尾流出相当于没有返回值;的结果是undefined.

唯一的例外是main()函数,它允许缺少return语句。第3.6.1/5段:

main中的return语句具有离开main函数的效果(自动销毁任何对象)存储持续时间),并以返回值作为参数调用std::exit如果控制到达结束在没有遇到返回语句的情况下执行main,效果是执行

return 0;
最后

:

为什么它工作?

未定义行为意味着你的程序可以在某些机器上运行,但不能在其他机器上运行;或者它今天可以在所有的机器上运行,但不是明天;或者它会导致你的程序产生一些奇怪的、不可预测的结果;包括(这是最糟糕的情况)似乎运行得很好。

您所拥有的是未定义行为,因为您正在流出承诺返回某些内容的函数的末尾。

在c++中唯一合法的函数是int main()(和带参数的版本),因为它在没有return语句的情况下隐式返回0

检查编译后产生的asm代码。我的猜测是,这个函数返回什么发生在寄存器AX(这是c-call标准函数实现,如果我没弄错的话)。在你的情况下,它恰好是你想要的……

这是非法的,如果它编译了,那么在某种程度上它为运行时存储了一些奇怪的东西。并且必须从函数返回*this。正确的函数定义如下:

Foo& operator=(const Foo& _foo)
{    
  if(this == &_foo) /* check for self-assignment */
     return *this;
  str = _foo.str;
  return *this;
}

返回*this是必须的链式赋值,如:

Foo  x, y, z;
x = y = z;     /* *this is necessary for this statement */