为什么允许赋值运算符返回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;
}
问题:
我在很多地方读过“赋值运算符应该返回* 这个,这样你就可以进行赋值链接”这完全有意义,但为什么上面的工作呢?
答案 0 :(得分:7)
为什么这是合法的? (为什么要编译)
不合法,并在您的程序中注入未定义的行为。你的编译器至少应该警告你(如果你设置了足够高的警告级别,我相信它会这样做。)
根据C ++ 11标准的第6.6.3 / 2段:
离开函数末尾相当于没有值的返回; 这导致未定义 价值回归函数中的行为。
唯一的例外是main()
函数,允许缺少return
语句。根据第3.6.1 / 5段:
main
中的return语句具有离开main
函数的效果(使用自动销毁任何对象) 存储持续时间)并以返回值作为参数调用std::exit
。 如果控制到达终点main
没有遇到return语句,效果是执行return 0;
最后:
为什么会这样?
未定义的行为意味着您的程序可能在某些计算机上运行但在其他计算机上运行;或者它今天可以在所有机器上运行,但不能在明天运行;或者它会导致你的程序有一些奇怪的,不可预测的结果;包括(这是最差的案例)似乎运行得非常好。
答案 1 :(得分:2)
你所拥有的是未定义的行为,因为你正在流失一个承诺返回某个东西的函数的末尾。
在C ++中执行此操作的唯一函数是int main()
(以及带参数的版本),因为它在没有return语句的情况下隐式返回0
。
答案 2 :(得分:0)
检查编译后生成的asm代码。我的猜测是这个函数返回寄存器AX中发生的事情(如果我没弄错的话,这是c调用标准函数实现)。在你的情况下,它恰好是你想要它...如果你添加一些功能,你可能会打破它...
答案 3 :(得分:0)
它是非法的,如果它以某种方式编译它会为运行时存储一些奇怪的东西。你必须从这个函数返回* this。正确的函数定义将类似于
Foo& operator=(const Foo& _foo)
{
if(this == &_foo) /* check for self-assignment */
return *this;
str = _foo.str;
return *this;
}
返回*这对于像
这样的链分配是必须的Foo x, y, z;
x = y = z; /* *this is necessary for this statement */