Reputation: 37
Some discussion warns about dangling reference, with R-Value reference. I do not see any dangling reference in the following example as DTOR was called when main() terminates. Am I missing something?
class test_ctor
{
public:
explicit
test_ctor(int x = 1):_x(x)
{
std::cout << "CTOR: " << _x << "\n";
}
~test_ctor()
{
std::cout << "DTOR: " << _x << "\n";
}
test_ctor(test_ctor const & y) = default;
test_ctor(test_ctor && y) = default;
int _x;
};
test_ctor test_rvalue()
{
test_ctor test = test_ctor(2);
return test;
}
Now I can use the above code in two ways:
int main(int argc, const char * argv[]) {
auto test = test_rvalue();
std::cout << " test: " << test._x << " \n";
return 0;
}
Or
int main(int argc, const char * argv[]) {
auto && test = test_rvalue();
std::cout << " test: " << test._x << " \n";
return 0;
}
both case has the same output:
CTOR: 2
test: 2
DTOR: 2
Which means both are efficient ways to return object. Are there any side effects in r-value reference?
Upvotes: 1
Views: 709
Reputation: 275575
In c++11:
auto test = test_rvalue();
moves the return value of test_rvalue()
into test
. This move is then elided by every non-brain damaged compiler so it never happens. The move constructor still needs to exist, but is never called, and any side effects of moving do not occur.
auto&& test = test_rvalue();
binds an rvalue reference to the temporary returned by test_rvalue()
. The temporaries lifetime is extended to match that of the reference.
In c++17:
auto test = test_rvalue();
the prvalue return value of test_rvalue()
is used to directly construct the variable test
. No move, elided or not, occurs.
The auto&&
case remains unchanged from c++11.
Upvotes: 2