【发布时间】:2019-03-06 19:40:23
【问题描述】:
我从三元运算符中得到了非常奇怪的结果,它应该返回对链表成员对象的引用。我的数据库对象中有这样的成员函数:
Month& GetLastMonth() { return months_.Size() > 0 ? months_.Last() : Month(); }
我在代码中调用了这个函数 2 次:在加载 DB 以获取信息之后,以及在更改月份的某些参数并按下按钮时。
我第一次将它写入 const 引用,这里没什么大不了的。但是第二次我需要非常量引用来重新计算月份(所以它也会在数据库中改变)。
但是,一些黑魔法发生了,而不是预期的结果。每次我调用GetLastMonth() 函数时,它都会返回一个具有不同地址的引用。因此,在 DB 加载之后 - 它的 1 个地址,重新计算月份 - 它的第 2 个地址,并且在保存到它的第 3 个地址之后。当然,正因为如此,我重新计算月份后的更改不会保存到文件中。
现在,months_ 的大小始终为 1(用于测试目的)。它也是链表,所以 Month 永远不能重新分配。我已经测试过了,它从不调用Month(),所以看起来三元运算符工作正常。
这样调用,结果相同:
Month& GetLastMonth() { return months_.Size() ? months_.Last() : Month(); }
但是如果我不使用三进制来称呼它:
Month& GetLastMonth() { return months_.Last(); }
或者用正确的if():
Month& GetLastMonth()
{
if(months_.Size() > 0)
{
return months_.Last();
}
return Month();
}
它按预期工作,并返回所有 3 次相同地址的引用。我在考虑这个晦涩的事情大约 2 天,但仍然找不到任何背后的原因。
【问题讨论】:
-
请注意,返回
Month()是特定于 MS 的扩展(因为它会绑定到非 const 左值引用)。它不适用于标准 C++。 -
您可能应该将返回类型更改为
Month,而不是Month&,因为您正在返回一个临时的。 -
@tadman OP 想要非常量引用。
-
@tadman 是的,我现在看到返回临时对象作为参考确实是个坏主意...我将尝试重构代码,并想出一些更好的方法来防止访问空列表...
-
一种更 C++ 的方法是返回一个可能等于
months.end()的迭代器,例如没有找到条目,或者抛出异常。如果这是一个容器,使其符合 C++ 容器的期望和标准通常是一个好主意。
标签: c++ reference return ternary-operator