Jeśli dobrze rozumiem to poprawne, a=std::move(b)
wiąże się odwoływać a
na adres b
. A po tej operacji zawartość, na którą wskazuje b, nie jest gwarantowana.
Ach, no: a
nie koniecznie jest odwołaniem. Powyższy wykorzystanie std::move
również udziela pozwolenia kompilatora, aby zadzwonić decltype(a)::operator=(decltype(b)&&)
jeśli istnieje: takie operatory przypisania są stosowane, gdy podczas przypisania do a
wartość b
nie musi być zachowany, ale b
muszą być nadal pozostaje w pewnym stanu używalności dla zniszczenie.
Jednak nie sądzę, że ma to jakiś sens dla std::move
elementu w tablicy. Co stanie się, jeśli a=std::move(b[n])
?
Może mieć sens ... oznacza to, że poszczególne elementy tablicy mogą być efektywnie przypisane/przeniesione do innej zmiennej, ale tylko jeden raz na element.
Na przykład, jeśli miał wektor z std::string
członków danych i używane idiom erase-usunięcia:
v.erase(std::remove_if(std::make_move_iterator(std::begin(v)),
std::make_move_iterator(std::end(v)),
[] (const X& x) { return ...condition...; }).base(),
std::end(v));
Powiedzmy końcowy wynik biorąc pod uwagę elementy wektora i kondycję powyżej jest to, że remove_if
zagęszcza elementy zachowane z przodu v
przez wykonanie v[1] = v[3];
: std::string::operator=(std::string&& rhs)
najprawdopodobniej zamieniają bufory (tj. zamieniają wskaźniki na początek/koniec danych tekstowych i koniec zarezerwowanej pamięci), zamiast kopiować tekst w poprzek, co może być szybsze - zwłaszcza gdy bieżący bufor v[1]
jest zbyt mały, aby pomieścićWartość 210 takich, że v[1]
musiałby w przeciwnym razie delete[]
jego stary bufor następnie new[]
większy bufor, a następnie skopiować dane tekstowe.
Aktualizacja: podane ta odpowiedź przyciągnął sporo głosów, pomyślałem, że mięso to z żywą przykład:
This full program on ideone.com ilustruje to w akcji - cesja ruch jest używany trzy razy, aby skopiować zatrzymywane nawet wartości ponad wcześniej zużytych wartości nieparzystych przez ten kod:
std::vector<X> v{2, 1, 8, 3, 4, 5, 6};
v.erase(std::remove_if(std::make_move_iterator(std::begin(v)),
std::make_move_iterator(std::end(v)),
[] (const X& x) { return x.n_ & 1; }).base(),
std::end(v));
z struct X
z ruchem operatora przypisania drukowania "=(X&&) "
i końcowy zrzut v
, wyjście jest:
=(X&&) =(X&&) =(X&&) 2 8 4 6
* "Jeśli dobrze rozumiem to prawidłowe,' a = std :: posunięcie (b) '' A' wiąże odniesienie do adresu 'B'" * Tylko jeśli jest to deklaracja, a "a" jest typu referencyjnego. W przeciwnym razie jest to zadanie przeniesienia. Na przykład. jeśli 'a' i' b' są 'std :: vector', wskaźnik do magazynu sterty, który zarządza wektorami, jest kopiowany z 'b' do' a', a 'b' zmienia się tak, by wskazywał gdzie indziej. –
dyp
Iteratory to abstrakcja wskaźników. Odwołanie do wskaźnika daje wartość * l *: 'int i = 42; int * p = & i; 'then' * i' jest lwartością. Podobnie dla iteratorów. Oznacza to jednak, że algorytmy zazwyczaj kopiują wartości, do których odwołują się iteratory.'move_iterator' sprawia, że' * it' zwraca wartość r. – dyp