Reputation: 23135
The answer to this question points out that you shouldn't return references to parameters, as they may be temporaries which may be out of scope, and will not be preserved if the result is assigned to a reference.
Following that logic, doesn't the following code have a similar problem?
#include <iostream>
class T
{
public:
T& operator+=(const T& t) { this->x += t.x; return *this; }
T(int x) : x(x) {}
int x;
~T()
{
std::cout << "My value is " << this->x << " and I'm dead." << std::endl;
this->x = -999;
}
};
int main()
{
const T& t = (T(2) += T(3));
std::cout << t.x << std::endl;
}
And if so, how should I write the +=
operator to avoid this problem?
I also imagine there would be problems with the following code in C++11, but I haven't checked it:
#include <iostream>
#include <string>
int main()
{
for ( char x : std::string("hello") += std::string("world") )
{
std::cout << x << std::endl;
}
}
It would seem as a result you should never return references to function parameters, unless you are prepared to risk undefined behaviour in range based for loops.
Upvotes: 3
Views: 154
Reputation: 76788
For cases like this, returning a reference to *this
is the expected behavior (this is done to enable Method Chaining). Since this
is not a local variable of the function, it will not go out of scope return.
About the second part of your question, the range based for-loop in your case is defined to equivalent to this (§ 6.5.4 [stmt.ranged]):
{
auto && __range = std::string("hello") += std::string("world");
for ( auto __begin = begin(__range),
__end = end(__range);
__begin != __end;
++__begin ) {
char x = *__begin;
std::cout << x << std::endl;
}
}
As you see, the string you iterate over is captured using auto &&
, which can bind the const-reference returned by +=
.
Edit As Martinho points out in his comment, +=
returns a non-const reference, so the code shown there is undefined behavior.
Upvotes: 1