Can someone explain to me why output for R-value is different from L-value?
#include <iostream>
#include <vector>
using namespace std;
template<typename Ct>
struct ct_wrapper {
Ct&& ct; // R or L ref
explicit ct_wrapper(Ct&& ct)
: ct(std::forward<Ct>(ct)) { std::cout << this->ct[1];};
};
int main() {
// L-val
vector<int> v{1,2,3};
ct_wrapper<vector<int>&> lv(v);
cout << endl << lv.ct[0] << lv.ct[1] << lv.ct[2] << endl;
// R-val
ct_wrapper<vector<int>&&> rv(vector<int>{1,2,3});
cout << endl << rv.ct[0] << rv.ct[1] << rv.ct[2] << endl;
}
Output (same for gcc48 and clang32):
2
123
2
003
Answer
It was buried somewhat in my chat with Johannes Schaub, so I’ve put it here.
When temporary vector initializes r-value-ref member-variable rv.ct, temporary lifetime is not extended because there’s a special exception: [class.temporary]p5: “A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.”
Because your member is just a reference. In the second case the object it references is already dead after the definition of the local
rvvariable has finished. So the later access in thecoutis undefined behavior.