1. „Co to jest?”
Chociaż std::move()
technicznie jest to funkcja - powiedziałbym, że tak naprawdę nie jest funkcją . Jest to rodzaj konwertera między sposobami, w których kompilator uwzględnia wartość wyrażenia.
2. „Co to robi?”
Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że std::move()
tak naprawdę nic nie rusza . Konwertuje wyrażenie od bycia lwartość (takich jak zmiennej o nazwie) do bycia xvalue . Wartość x mówi kompilatorowi:
Możesz mnie ograbić, przenieść wszystko, co trzymam i użyć go gdzie indziej (bo i tak wkrótce mnie zniszczą).
innymi słowy, kiedy używasz std::move(x)
, pozwalasz kompilatorowi na kanibalizację x
. Zatem jeśli x
, powiedzmy, ma własny bufor w pamięci - po std::move()
kompilacji może zamiast niego posiadać inny obiekt.
Możesz także przejść z prvalue (np. Tymczasowego mijania), ale jest to rzadko przydatne.
3. „Kiedy należy go użyć?”
Innym sposobem na zadanie tego pytania jest: „Po co miałbym kanibalizować zasoby istniejącego obiektu?” cóż, jeśli piszesz kod aplikacji, prawdopodobnie nie będziesz się zbytnio bawić w tymczasowe obiekty tworzone przez kompilator. Zasadniczo robiłbyś to w miejscach takich jak konstruktory, metody operatora, funkcje podobne do algorytmów biblioteki standardowej itp., W których obiekty są często tworzone i niszczone automatycznie. Oczywiście to tylko ogólna zasada.
Typowym zastosowaniem jest „przenoszenie” zasobów z jednego obiektu do drugiego zamiast kopiowania. @Guillaume prowadzi do tej strony, która ma prosty krótki przykład: zamiana dwóch obiektów przy mniejszym kopiowaniu.
template <class T>
swap(T& a, T& b) {
T tmp(a); // we now have two copies of a
a = b; // we now have two copies of b (+ discarded a copy of a)
b = tmp; // we now have two copies of tmp (+ discarded a copy of b)
}
użycie move pozwala zamienić zasoby zamiast je kopiować:
template <class T>
swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
Pomyśl o tym, co się stanie, gdy T
powiedzmy vector<int>
rozmiar n. W pierwszej wersji czytasz i zapisujesz 3 * n elementów, w drugiej wersji w zasadzie odczytujesz i zapisujesz tylko 3 wskaźniki do buforów wektorów oraz rozmiary 3 buforów. Oczywiście klasa T
musi wiedzieć, jak się poruszać; twoja klasa powinna mieć operator przypisania ruchu i konstruktor ruchu, aby klasa T
działała.