Consider the following code:
struct MyString
{
// some ctors
MyString& operator+=( const MyString& other ); // implemented correctly
};
MyStrin
The example you are looking for is a range-based for
statement:
MyString a, b, c;
for( MyCharacter mc : a + b + c ) { ... }
In this case the result of a + b + c
is bound to a reference, but the nested temporary (generated by a + b
and returned as an rvalue reference by (a + b) + c
) is destroyed before the range-based for loop is executed.
The standard defines range-based for loops in
6.5.4 The range-based for statement [stmt.ranged]
1 For a range-based
for
statement of the form
for (
for-range-declaration:
expression)
statementlet range-init be equivalent to the expression surrounded by parentheses
( expression )
and for a range-based
for
statement of the form
for (
for-range-declaration:
braced-init-list)
statementlet range-init be equivalent to the braced-init-list. In each case, a range-based
for
statement is equivalent to{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
Note that auto && __range = range-init;
would extend the lifetime of a temporary returned from range-init, but it does not extend the lifetime of nested temporaries inside of range-init.
Instead of asking for trouble, you should trust the string's own move constructor:
MyString operator+(MyString lhs, MyString rhs)
{
lhs += std::move(rhs);
return std::move(lhs);
}
Now both MyString x = a + b;
and MyString y = MyString("a") + MyString("b");
work efficiently.