我从三元运算符中获得了非常奇怪的结果,该运算符应该返回对链表的成员对象的引用。我的数据库对象中有如下成员函数:
DB::table("users")->insert([
"password" => $request->input("password"), // or $request["password"]
...
]);
我在代码中两次调用了此函数:在加载数据库以获取信息之后,以及在更改月份的某些参数并按下按钮时。
我第一次将其写入const引用,这里没什么大不了的。但是第二次我需要非常量引用来重新计算月份(因此它也会在数据库中更改)。
但是发生了一些不可思议的事情,而不是预期的结果。每次调用Month& GetLastMonth() { return months_.Size() > 0 ? months_.Last() : Month(); }
函数时,它都会返回一个具有不同地址的引用。因此,在DB加载后-它的1个地址,重新计算月份-它的第二个地址,并保存到文件的第三个地址之后。当然,因此,重新计算月份后的更改不会保存到文件中。
现在,GetLastMonth()
的大小始终为1(出于测试目的)。它也是链表,因此Month永远都无法重新分配。我已经对其进行了测试,并且它从未调用过months_
,所以似乎三元运算符工作正常。
这样调用,会得到相同的结果:
Month()
但是,如果我不使用三进制调用它的话:
Month& GetLastMonth() { return months_.Size() ? months_.Last() : Month(); }
或使用适当的Month& GetLastMonth() { return months_.Last(); }
:
if()
它按预期方式工作,并且全部3次返回具有相同地址的引用。我已经花了大约两天的时间来思考这个晦涩的事情,但仍然找不到背后的任何理由。
答案 0 :(得分:3)
三元运算符会找到两个操作数的通用类型和值类别,而在其他两种情况下不会发生这种情况,这就是为什么它在这里起作用的原因。
months_.Last()
和Month()
都具有类型Month
,所以一切都很好。但是现在,让我们检查值类别。 months_.Last()
是左值,而Month()
是prvalue!因此,此处的公用值类别是prvalue,并且两个操作数都转换为prvalue。这意味着您每次(从副本中)都从Month
获得一个新的months_.Last()
!
但是请再次注意,这是MS特定的扩展名。如果没有该扩展名,则代码将无效,因为您将尝试将条件运算符返回的prvalue绑定到非const左值引用。