2016-06-01 12 views

Odpowiedz

8

Opis normy nie jest wystarczająco jasny.

$ 23.3.6.5 wektorowe modyfikatory [vector.modifiers]:

Uwagi: Powoduje realokacji jeśli nowy rozmiar jest większy niż stary pojemności. Jeśli nie nastąpi żadna realokacja, wszystkie iteratory i odwołania przed punktem wstawiania pozostają poprawne.

Więc kiedy dodać elementy do std::vector realokacji na pewno stanie, gdy nowy rozmiar jest większy niż wydajności prądowej, ale nie mówi realokacja nie stanie, nawet jeśli nowa wielkość jest mniejsza lub równa wydajności prądowej . W każdym razie, jeśli realokacja nie nastąpi, wszystkie iteratory i odwołania do elementów przed punktem wstawienia muszą pozostać ważne, oznacza to, że dane nie zostaną przeniesione.

To samo dotyczy insert(), emplace_back(), emplace() i push_back().

Cytat cppreference.com tylko jako punkt odniesienia:

Jeśli nowy size() jest większa niż capacity() wtedy wszystkie iteratory i odniesienia (w tym iteracyjnej past-the-end) są unieważniane. W przeciwnym razie unieważniany jest tylko iterator z ostatniej chwili.

+0

@KerrekSB Czy uważasz, że opis na cppreference nie jest dokładny? (Powinien być naprawiony?) – songyuanyao

+3

Nie, jestem całkowicie przekonany, że celem jest zdolność do kontrolowania realokacji w obie strony. To tylko trochę niedbałe sformułowanie. Byłoby to obłędnie inaczej, i prawdopodobnie istnieje wiele prawdziwego kodu, który zależy od tego zachowania. –

+1

W rzeczywistości specyfikacja jest kompletna i hermetyczna, rozłożona jest na kilka sekcji. Zobacz moją zaktualizowaną odpowiedź. –

30

Specyfikacja jest nieco pośrednia. capacity jest określona jako:

size_type capacity() const noexcept; 

Returns: łączna liczba elementów, że wektor może przechowywać bez konieczności realokacji.

Druga część pochodzi z reserve:

reserve(size_type n); 

Uwagi: Realokacja unieważnia wszystkie odniesienia, wskaźniki i iteratory odnoszące się do elementów w sekwencji. Nie nastąpi ponowne przydzielanie podczas wstawiania po wywołaniu do reserve() do momentu, w którym wstawienie spowodowałoby zwiększenie rozmiaru wektora o wartość większą niż wartość capacity().

Z tego można wywnioskować, że jeśli rozmiar jest mniejszy niż pojemność, wstawienie nie powoduje realokacji.

Nie ma pojedynczego, bezpośredniego stwierdzenia, że ​​wektor nie przeniesie się, jeśli jest wolna pojemność i użytkownik nie nazwał jednoznacznie reserve. Jednakże, nie są generalnie wymagane pojemnik [container.requirements.general]

O ile nie zaznaczono inaczej (bezpośrednio lub poprzez określenie funkcji w odniesieniu do innych funkcji), wywoływanie funkcji składowej pojemnik lub pojemnik przechodząc jako argument funkcji bibliotecznej nie unieważnia iteratorów ani nie zmienia wartości obiektów w tym kontenerze.

Wreszcie mamy opis skutków wstawienia:

[insert/emplace_back/push_back:] 

Uwagi: Powoduje realokacji jeśli nowy rozmiar jest większy niż stary pojemności. Jeśli nie nastąpi żadna realokacja, wszystkie iteratory i odwołania przed punktem wstawienia zachowują ważność.

Łączenie wszystkich razem: O ile nie określono inaczej, wywoływanie funkcji składowej nie powoduje unieważnienia iteratorów. Realokacja unieważnia iteratory (opisane powyżej jako część reserve), więc jeśli nie określono inaczej, wywoływanie funkcji składowej, a w szczególności wstawiania, nie powoduje ponownego przydzielenia, Jedna z takich nadpisań podana jest dla przypadku, w którym nowy rozmiar przekracza bieżący Pojemność.

+0

Wygląda jak inny pod określonym zachowaniem. – NathanOliver

+2

@NathanOliver: Właściwie wszystko jest w porządku, tylko trochę rozłożone. Zobacz aktualizację. –

+0

@KerrekSB Porozmawiaj o konieczności wspólnego łączenia odpowiedzi :) Niestety, nie mogę cię powtórzyć. Dziękuję za poświęcony czas i wysiłek, aby wszystko to zmylić. – NathanOliver