Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why reference can not capture temporary while const ref and rval ref can [duplicate]

Why reference can not capture temporary value while const reference and rvalue reference can capture and prolong object life. In other words while two first lines are legal but third not:

const string &a = string("a");
string &&b = string("b");
string &c = string("c"); // why illegal?
like image 329
Trismegistos Avatar asked Mar 17 '26 15:03

Trismegistos


1 Answers

Quoting from N1377

Bjarne in his excellent text "The Design and Evolution of C++" discusses the motivation for prohibiting the binding of an rvalue to a non-const reference in section 3.7. The following example is shown:

void incr(int& rr) {rr++;}

void g()
{
    double ss = 1;
    incr(ss);
}

ss is not incremented, as a temporary int must be created to pass to incr(). The authors want to say right up front that we agree with this analysis 100%. Howard was even bitten by this "bug" once with an early compiler. It took him forever to track down what was going on (in that case it was an implicit conversion from float to double that created the temporary).

This rationale (for not binding rvalues to non-const (lvalue) references) held from the dawn of C++, up until C++11 (2011). However the same rationale does not apply to lvalue references to const:

It is "safe" to bind a temporary to an lvalue reference to const because the compiler will tell you if you accidentally make a "useless" modification to this temporary.

So why is it "safe" to bind an rvalue to an rvalue reference?

Again quoting from N1377:

Having said that, we would like to add: You don't ever want to bind a temporary to a non-const reference ... except when you do.

A non-const reference is not always intended to be an "out" parameter. Consider:

template <class T>
class auto_ptr
{
public:
    auto_ptr(auto_ptr& a);
    ...
};

The "copy" constructor takes a non-const reference named "a". But the modification of "a" is not the primary goal of this function. The primary goal is to construct a new auto_ptr by pilfering "a". If "a" happens to refer to an rvalue, this is not a logical error!

In summary, sometimes you want to modify an rvalue, and sometimes you don't. The different types of references allow the programmer to tell the compiler which situation they are in.

The bindings in your question are a logical conclusion of the bindings motivated by N1377.

The move semantics proposal did put effort into coming up with a solution that did not require language changes (i.e. the introduction of the rvalue reference). However library only solutions were unsatisfactory as the resulting syntax for building things like move constructors was overly complex.

like image 110
Howard Hinnant Avatar answered Mar 19 '26 04:03

Howard Hinnant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!