Reputation: 20780
In the project I work I saw code very similary with next one:
std::string str = (std::string() += "some string") += "some other string";
For obvious reasons I can't reproduce the original code, but I can say it uses custom String
and operator<<
that has same behavior as operator+=
for std::string
.
I feel something is very wrong here, beside the creation/destruction of unnecessary temporary objects, but I don't know exactly what.
Are the temporary objects const
? Is yes, how does this code compile(VS2010) because operator +=
mutates the object? Can you please explain what are the problems here?
Upvotes: 4
Views: 233
Reputation: 3249
To make the lifetime point clearer, the standard says (12.2):
Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.
And (1.9):
A full-expression is an expression that is not a subexpression of another expression.
In this case this would (to my best knowledge) be the call to std::string
s move constructor (which you technically do with the =
initialization) with (std::string() += "some string") += "some other string"
. So, put simply, the lifetime of a temporary ends at the ;
, which means you are safe here.
Upvotes: 1
Reputation: 22890
(std::string() += "some string") += "some other string";
can be broke into
temp1(std::string());
temp1 += "some string"
temp1 += "some other string";
The parenthesis define the precedence over both += operations. It does not define a scope, so temp1 is not destroyed by any means when this statement is executed.
On the other side the C++ Standard guaranties that both string literals have the lifetime of the program.
Thus, there is a minimal amount of temporary object on this code sample.
It can go for an arbitrary amount of literals
std:string str = ((((((std::string() += "a") += "b") += "c") += "d") += "e") += "f");
Upvotes: 2
Reputation: 157354
Temporary objects are not const
; they are rvalues. That means they can bind to a const reference (C++03) or a (const or non-const) rvalue reference (C++11).
In addition, you can call non-const member functions on temporaries, including member operators; this is presumably what is happening in this case. Calling non-const member operators is dangerous as it can lead to leaking dangling references, but in this case you're OK as there are no references persisting outside the expression.
In C++11 we have rvalue references, so the expression can be rewritten more clearly and more safely as:
std::string str = std::string() + "some string" + "some other string";
The content of the string
temporary is reused by the free operator+
via a move constructor; temporaries are left in a moved-from state.
Upvotes: 3