Lifetime extension and the conditional operator

2019-02-05 19:55发布

local lvalue references-to-const and rvalue references can extend the lifetime of temporaries:

const std::string& a = std::string("hello");
std::string&& b = std::string("world");

Does that also work when the initializer is not a simple expression, but uses the conditional operator?

std::string&& c = condition ? std::string("hello") : std::string("world");

What if one of the results is a temporary object, but the other one isn't?

std::string d = "hello";
const std::string& e = condition ? d : std::string("world");

Does C++ mandate the lifetime of the temporary be extended when the condition is false?

The question came up while answering this question about non-copyable objects.

2条回答
爷的心禁止访问
2楼-- · 2019-02-05 20:18
std::string d = "hello";
const std::string& e = condition ? d : std::string("world");

Does C++ mandate the lifetime of the temporary be extended when the condition is false?

It will be. The conditional is an rvalue expression, and when bound with a const reference the compiler will create an unnamed object and bind the reference to it. What I am not 100% sure is whether the temporary whose lifetime is extended is std::string("world") or whether a copy of it is (conceptually) made (and elided).

查看更多
男人必须洒脱
3楼-- · 2019-02-05 20:28

Both of those are fine.

§5.16 says (extraordinarily abridged):

2 If either the second or the third operand has type void

Nope.

3 Otherwise, if the second and third operand have different types

Nope.

4 If the second and third operands are glvalues of the same value category

Nope. (In the first, both are prvalues and in the second one is a glvalue and one is a prvalue.)

5 Otherwise, the result is a prvalue

Okay, so both of these result in prvalues. So the binding is fine, but what's the binding to?

6 Lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are per- formed on the second and third operands.

Okay, so both are now rvalues if they weren't already.

6 (continued) After those conversions, one of the following shall hold:

The second and third operands have the same type; the result is of that type. If the operands have class type, the result is a prvalue temporary of the result type, which is copy-initialized from either the second operand or the third operand depending on the value of the first operand.

Okay, so it's either std::string(first_operand) or std::string(second_operand).

Regardless, the result of the conditional expression is a new prvalue temporary, and it's that value that's extended by binding to your references.

查看更多
登录 后发表回答