Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does initializing non-const reference by rvalue work (in C++11)?

Tags:

c++

c++11

rvalue

The following example code compiles.

#define USE_RVALUE // line 1

template<class data_type>
class Container
{
    data_type& data;
public:
#ifdef USE_RVALUE
    Container(data_type&& _data) : data(_data) {}
#endif
    Container(data_type& _data) : data(_data) {}
};

int main()
{
    double d = 42.0;
    Container<double> c1(d);
    Container<double> c2(1.0f); // line 18
    return 0;
}

My compiler command:

g++ -std=c++11 -Wall ref.cpp -o ref # g++ is 4.7.1

If we outcomment line 1, g++ complains:

no matching function for call to ‘Container<double>::Container(float)’
ref.cpp:18:34: note: candidates are:
ref.cpp:11:9: note: Container<data_type>::Container(data_type&) [with data_type = double]
ref.cpp:11:9: note:   no known conversion for argument 1 from ‘float’ to ‘double&’
[... (more candidates)]

Of course, the error is clear, and a typical error in C++03: References from rvalues are not allowed, if these rvalues are not const. But why does it work with the rvalue constructor (i.e. the #ifdef enabled)? We have the same situation in the initializer list: Reference from non-const value.

Also, if you explain it... Is this code "good coding style" or "to avoid"?

like image 738
Johannes Avatar asked Mar 20 '26 02:03

Johannes


1 Answers

The answer is simple enough: whatever has name - it is an lvalue. So in your ctor, with rvalue reference, _data is an lvalue in the body of ctor despite the fact it is an rvalue in the outer world. So at the end you have a dangling reference so you should not do such a thing.

Basically, when you accept something by &&(except when in template, aka Universal references) you should treat it as "this value are going to be destroyed". So you should steal from it, change it, whatever(except leaving it in some invalid state preventing its normal destruction). But you should never store pointer or reference to it. Because this object maybe destroyed right after your function complete. It is exactly the case you have. double(1.0f) exists in your ctor body only and has no meaning outside it and you still store reference to it.

like image 113
ixSci Avatar answered Mar 21 '26 16:03

ixSci



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!