简体   繁体   English

三元运算符在return语句中给出意外结果

[英]Ternary operator gives unexpected results in return statement

I'm getting very weird results from ternary operator that should return reference to member object of a linked list. 我从三元运算符得到非常奇怪的结果,应该返回对链表的成员对象的引用。 I have member function in my database object like this: 我在我的数据库对象中有成员函数,如下所示:

Month& GetLastMonth() { return months_.Size() > 0 ? months_.Last() : Month(); }

I call this function 2 times in code: right after loading DB to get info, and when changing some parameters of month and pushing a button. 我在代码中调用了这个函数2次:在加载DB以获取信息后,以及更改月份的某些参数并按下按钮时。

First time I write it to const reference, no big deal here. 我第一次把它写成const参考,这里没什么大不了的。 But second time I need non-const reference to recalculate month (so it will change in DB too). 但第二次我需要非const引用来重新计算月份(因此它也会在DB中发生变化)。

But instead of expected results, some black magic happens. 但不是预期的结果,一些黑魔法发生。 Every time I call GetLastMonth() function it returns a reference with different address. 每次调用GetLastMonth()函数时,它都会返回一个具有不同地址的引用。 So, after DB loads - its 1 address, recalculating month - its 2nd address and right after saving to file its 3rd address. 所以,在DB加载后 - 它的1个地址,重新计算月份 - 它的第2个地址,并在保存到第3个地址之后立即加载。 Of course, because of this, my changes after recalculating month are not saved to file. 当然,因此,我重新计算月份后的更改不会保存到文件中。

Now, size of months_ are always 1 (for testing purposes). 现在, months_大小始终为1(用于测试目的)。 Also it's linked list, so Month can never reallocate. 它也是链表,因此Month永远不会重新分配。 I've tested it, and it never calls Month() , so seems like ternary operator is working fine. 我测试了它,它从不调用Month() ,所以看起来三元运算符工作正常。

Calling it like this, gives same result: 像这样调用它会得到相同的结果:

Month& GetLastMonth() { return months_.Size() ? months_.Last() : Month(); }

Howerver if I call it without ternary: 如果我在没有三元的情况下称它为Howerver:

Month& GetLastMonth() { return months_.Last(); }

Or with proper if() : 或者使用正确的if()

Month& GetLastMonth()
{ 
    if(months_.Size() > 0)
    {
        return months_.Last();
    }
    return Month();
}

It works as expected and returns reference with same address all 3 times. 它按预期工作,并返回具有相同地址的引用3次。 I was thinking about this obscure thing for about 2 days, but still can't find any reasoning behind this. 我在考虑这个不起眼的事情大约2天,但仍然找不到任何理由。

Edit: Related question: Return type of '?:' (ternary conditional operator) 编辑:相关问题: 返回类型'?:'(三元条件运算符)

The ternary operator finds a common type and value category of both operands, and this doesn't happen for the two other cases, which is why it works there. 三元运算符找到两个操作数的公共类型值类别,对于其他两种情况,这不会发生,这就是它在那里工作的原因。

months_.Last() and Month() both have type Month , so everything is fine there. months_.Last()Month()都有类型Month ,所以一切都很好。 But now, let's examine the value categories. 但现在,让我们来看看价值类别。 months_.Last() is an lvalue, while Month() is a prvalue! months_.Last()是一个左值,而Month()是一个prvalue! So, the common value category here is a prvalue, and both operands get converted to a prvalue. 因此,这里的公共值类别是prvalue,并且两个操作数都转换为prvalue。 Which means that you get a new Month from months_.Last() every time (from the copy)! 这意味着你得到一个新的Monthmonths_.Last()从副本)每一次!

Note again however, that this is a MS specific extension. 但请注意,这是MS特定的扩展。 Without that extension, the code would be invalid, as you would try to bind the prvalue returned by the conditional operator to a non-const lvalue reference. 如果没有该扩展,代码将无效,因为您将尝试将条件运算符返回的prvalue绑定到非const左值引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM