2012-10-29 9 views
32

Co mówi standard C++ 11 na temat przypisania przesunięcia w stosunku do biblioteki standardowej? Aby być bardziej konkretnym, co, jeśli w ogóle, jest gwarantowane o tym, co robi selfAssign?Co gwarantuje standardowa biblioteka dla zadania przeniesienia?

template<class T> 
std::vector<T> selfAssign(std::vector<T> v) { 
    v = std::move(v); 
    return v; 
} 
+4

@ Mark Nie sądzę, że jest to duplikat. To pytanie dotyczy pisania własnego. To pytanie dotyczy tego, co gwarantuje standardowa biblioteka. –

+2

Zauważ, że to * nie * wiąże się z przypisaniem self-move 'T'. – Xeo

+0

@Xeo Usunąłem tę linię. Dzięki za wskazanie błędu. –

Odpowiedz

31

17.6.4.9 Argumenty funkcji [res.on.arguments]

1 Każdy z poniższych odnosi się do wszystkich argumentów do funkcji zdefiniowanych w C++ biblioteki standardowej, o ile wyraźnie nie zaznaczono inaczej.

...

  • Jeśli argumentem funkcji wiąże się z parametrem odniesienia rvalue, implementacja może zakładać, że parametr ten jest unikalnym odniesienie do ten argument. [Uwaga: Jeśli parametr jest parametrem generycznym postaci T & & i l wartość typu A jest powiązany, argument jest powiązany z wartością odniesienia o wartości l (14.8.2.1) i dlatego nie jest objęty poprzednim zdaniem . - nota końcowa] [Uwaga: Jeśli program rzuci wartość l do wartości o wartości , przekazując tę ​​lwartośc do funkcji bibliotecznej (np. Przez wywołanie funkcji z argumentem move (x)), program jest skutecznie prosząc tę ​​funkcję do traktuj tę lwartość jako tymczasową. Implementacja jest bezpłatna, aby zoptymalizować kontrole aliasingu z zewnątrz, które mogą być potrzebne, jeśli argument był wartością bezwzględną. -endnote]

więc realizacja std::vector<T, A>::operator=(vector&& other) wolno zakładać, że other jest prvalue. A jeśli other jest wartością prieniczną, samodzielne przeniesienie nie jest możliwe.

Co może się zdarzyć:

v zostanie pozostawiony w mniej zasobów państwa (0 pojemności). Jeśli v ma już pojemność 0, to będzie to operacja "no-op".

Aktualizacja

latest working draft, N4618 została zmodyfikowana tak, aby jednoznacznie stwierdzić, że w wymogami MoveAssignable wyrażenie:

t = rv 

(gdzie rv jest rvalue) t musi być tylko ekwiwalent wartości rv przed przypisaniem, jeśli t i rv nie odnoszą się do tego samego obiektu. I niezależnie, stan rv jest nieokreślony po przypisaniu.Istnieje dodatkowa uwaga do dalszego wyjaśnienia:

rv musi nadal spełniać wymagania składnika biblioteki, który używa go, czy nie t i rv odnoszą się do tego samego obiektu.

+4

Jeśli dobrze zrozumiałem Twój cytat, funkcja 'selfAssign' następnie wywołuje niezdefiniowane zachowanie, ponieważ warunki wstępne operatora przypisania przeniesienia nie są spełnione. Rozumiem, że 'std :: swap' wykona samoczynne przeniesienie przy wywołaniu' std :: swap (v, v) '. Czy to niezdefiniowane zachowanie wywoływać 'std :: swap (v, v)'? –

+0

Interesujące. Oznaczałoby to, że '&&' oznacza '__restrict' dla argumentów; Zastanawiam się, czy jakikolwiek kompilator jeszcze to wykorzystuje. –

+1

@MatthieuM .: Tylko to, co standard mówi o * jego własnych funkcjach; to nie jest ogólne stwierdzenie na temat parametrów "&&". Nie będziesz ograniczony do tego w kodzie, który napiszesz. –

0

Nic się nie wydarzy. Inteligentny operator przypisania może natychmiast wrócić, jeśli &other == this. W przeciwnym razie będzie przypisywać sobie wewnętrzne elementy, nie robiąc nic.

+0

Tak, ale tutaj członkowie rwart są tacy sami. Czy próbujesz powiedzieć, że w końcu wszystko jest stracone? –

+0

Nie, robię dziś kiepską robotę czytając pytania. Przepraszam. –

+0

Mam nadzieję, że to lepiej odpowie na twoje pytanie. –