11

I have this C++ test code snippet,

#include <vector>

class A {
        std::vector<int> x;
public:
        A(std::vector<int>&& _x) : x(_x) {}
};

class B {
        A a;
public:
        B(std::vector<int>&& _x) : a(/*move(*/_x/*)*/) {}
};

I'm passing _x to B as rvalue reference, but it's getting converted to lvalue when passed into A's constructor and I have to use std::move() to make it work. My question is why _x is lvalue and not an rvalue reference in a()?

Samik
  • 575
  • 2
  • 8
  • 19
  • 3
    While the type of `_x` is 'r-value reference to std::vector', it is still an l-value as it has a name. You might want to use it more than once in your constructor, so it shouldn't be moved from on first use unless you explicitly want to. – Corristo Oct 31 '16 at 20:29

2 Answers2

8

Quote from WIKI

For safety reasons, some restrictions are imposed. A named variable will never be considered to be an rvalue even if it is declared as such. To get an rvalue, the function template std::move() should be used. Rvalue references can also be modified only under certain circumstances, being intended to be used primarily with move constructors.

O_Z
  • 1,515
  • 9
  • 11
  • Wikipedia is imprecise here. Type and value category are two orthogonal concepts; you cant *declare* the value category. E.g. the result of the expression `dynamic_cast(someObject)` is of type `lvalue-reference to SomeClass`, but it is an r-value. – Corristo Nov 01 '16 at 02:00
7

Anything that has a name is an lvalue reference. You have to use std::move on parameters to pass them on as rvalue references.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125