Узнать значение rvalue при вызове метода геттер на объект правосторонним значением


Предположим, у меня есть следующий код. В B есть конструктор копирования, который вызывает метод, копирующий ресурсы a.

Теперь у меня также есть конструктор перемещения. В этом случае a не должен быть скопирован, а просто "украсть" ресурсы из существующего a. поэтому я также реализовал init, принимая rvalue. Но, конечно, когда я пытаюсь вызвать его с параметром b.a, это lvalue...

Есть ли способ вызвать этот метод?

class A{

    A(const A&& a){
        // 'steal' resources from a
    }

    void init(A& a){
       // init this A from another A by copying its resources
    }

    void init(A&& a){
      // init this A from another A stealing its resources and tell the other a, it must not destroy resources upon destruction
    }
};

class B{
    A a;

    B(B& b){
      a.init(b.a)          
    }

    B(B&& b){
      a.init(b.a); // How to call init(A&& a)?  
    }

};
1 2

1 ответ:

b.a является lvalue, поэтому вам нужно применить std::move:

a.init(std::move(b.a));

Примечание: но почему b является lvalue в теле B(B&& b)?

Здесь тип параметра B&& b просто означает, что эта перегрузка конструктора будет выбрана вместо, скажем, B(const B& b) при вызове с rvalue.

B make_B() { return B(); }
B b1(make_B());            // B(B&&) chosen
B b2(b);                   // B(const B&) chosen
Но сам параметр является значением lvalue, потому что у него есть имя. Все, что делает std::move, - это делает его аргумент похожим на rvalue.