2016-09-26 9 views
1

Я понимаю, что когда базовый тип данных перемещается, он всегда будет выполнять копию.
Например, вы не можете перейти от int, и имеют оригинальный int значение не определено:Неявные методы перемещения всегда сохраняют фундаментальные данные?

#include <iostream> 

int main() { 

    int x = 100; 
    int y{std::move(x)}; 
    std::cout << x << " " << y; //always prints "100 100" 

} 

Означает ли это, что то же самое верно для основных типов данных внутри определяемых пользователем типов?

#include <iostream> 
#include <vector> 

struct Foo{ 
    int i = 100; 
    std::vector<int> vec={1,2,3,4,5}; //something that probably will have an invariant 
}; 

int main() { 

    Foo x; 
    Foo y{std::move(x)}; 
    std::cout << x.i << " " << y.i; //always print "100 100"? 

} 

Что говорит стандарт о сохранении этих основных значений типа после перемещения?

+7

Почему так много дискуссий о том, что вы можете сделать со значением, из которого вы перешли? Если вы собираетесь использовать его, пропустив его где-нибудь, не перемещайте его. –

+0

Я полностью согласен с вами. Я все равно хотел бы знать. –

+2

@PeteBecker Перемещенные объекты не уничтожаются. Есть много веских причин использовать их впоследствии, которые не препятствуют их перемещению. – Yakk

ответ

0

Это зависит от конструктора перемещения ваших данных. Например, конструктор перемещения std::vector будет обычно оставляет ваш вектор пустым, но, как вы сказали, состояние не указано.

Состояние int не будет изменено, поскольку они тривиально перемещаются конструктивно. Компилятор выполнит копирование с тривиальным перемещением конструктивных типов. Как @ T.C. изложенные в комментариях, это поведение требуется стандартом.

, если вы намерены использовать свой класс после того, как он был перемещен из, рассмотреть вопрос о внедрении собственного конструктора перемещения:

struct Foo { 
    int i = 100; 
    std::vector<int> vec={1,2,3,4,5}; 

    Foo(Foo&& foo) noexcept : i{std::move(foo.i)}, vec{std::move(foo.vec)} { 
     foo.vec = {}; // ensure it's empty 
     foo.i = 0; // ensure it's 0 
    } 
}; 
+0

Я думаю, что компилятор имеет право, если он того пожелает, генерировать код, который изменяет «перемещенный-из» 'int'. Конечно, мы можем поверить, что это странная реализация, и никакой настоящий компилятор никогда не сделает этого, но он по-прежнему действителен. Я спрашиваю, потому что я думаю, что вы должны избегать слова «должно» в вашем ответе - это подразумевает (ложно?), Что такое поведение требуется стандартом. –

+0

@AaronMcDaid Требуется. –

+0

Спасибо за конформацию @ T.C. , Я обновлю ответ. –

3

специальных функций-членов, которые компилятор генерирует определяются как в основном делают соответствующую операцию по каждому из члены класса (и базовые классы).

Значит, ваш struct Foo's i будет вести себя точно так же, как int, который был перемещен. То же самое для vector.