2014-09-30 1 views
0

У меня есть вопрос начинающего пользователя в настройке перемещения в C++ 11. Пусть говорят, что у меня есть класс А, снабженное оператором шаг распайка:Оператор присваивания C++ 11 для классов с объектами в качестве членов - Уровень начального уровня

class A 
{ 
public: 
    A(); 
    ~A(); 
    A& operator=(A&&); 
    ... 
} 

У меня есть класс B, содержащий класса А объект и при условии, с оператором присваивания шаг

class B 
{ 
public: 
    B(); 
    ~B(); 
    B& operator=(B&&); 
    ... 
private: 
    A Test; 
} 

Что было мышления является то, что оператор B присваивания движения будет вызывать оператор присваивания движения его члена, так что я попробовал этот метод:

B& B::operator=(B&& Other) 
{ 
    ... 
    Test = Other.Test; 
    ... 
    return *this; 
} 

Но это не работает, так как двигаться assignme nt класса A не вызывается.

Вместо этого я был в состоянии сделать работу программы с помощью этого метода:

B& B::operator=(B&& Other) 
{ 
    ... 
    Test = std::move(Other.Test); 
    ... 
    return *this; 
} 

Я не понимаю, почему первый метод не работает. Я думал, что, поскольку конструктор будет называть его конструкторы элементов, оператор переадресации должен делать то же самое. Я ошибаюсь, или я допустил ошибку в своем коде? Может кто-то объяснить, спасибо!

ответ

2

Other.Test не является выражением rvalue, так как имеет имя. OTOH std::move(Other.Test) имеет тип A и категорию значений xvalue (т. Е. Значение r). Таким образом, он может привязываться к конструктору перемещения.

(EDIT:.. Бесстыдно скопирована @ DYP Комментарий Спасибо, @dyp и @KerrekSB)

+0

@dyp Я не понимаю. Неверно ли говорить, что 'std :: move (Other.Test)' имеет тип rvalue, когда я имею в виду, что он возвращает ссылку rvalue? – Pradhan

+0

@Pradhan: Правильное утверждение состоит в том, что '' std :: move (Other.Test) '** является ** значением rvalue. Его тип - 'A'. –

+0

Это довольно педантичное замечание; 'std :: move' возвращает ссылку rvalue, но любой ссылочный-квалификатор типа любого выражения немедленно отбрасывается для формирования категории значений. I.e., выражение 'std :: move (Other.Test)' имеет тип 'A' и категорию значений * xvalue * (т. Е. A * rvalue *). – dyp

1

@Pradhan правильно - вам нужно использовать std::move для перемещения членов в реализации оператора присваивания шаг. Однако, если это все, что необходимо для реализации вашего механизма перемещения, вы можете объявить оператора использовать стандартную реализацию:

#include <memory> 

class A { 
public: 
    A() : p{} { } 
    ~A() { } 

    A &operator=(A &&) = default; 

    // Instead of: 
    // A &operator=(A &&other) { 
    //  p = std::move(other.p); 
    //  return *this; 
    // } 

private: 
    std::unique_ptr<int> p; 
}; 

int main() { 
    A a; 
    A b; 
    b = std::move(a); 

    return 0; 
} 
Смежные вопросы