2013-02-20 16 views
34

Mam dwa wektory:Kopiowanie std :: wektor: preferowanie przypisania lub std :: copy?

std::vector<int> v1, v2; 

// Filling v1 
... 

A teraz muszę skopiować v1 do v2. Czy jest jakiś powód, aby wolą

v2 = v1;

do

std::copy (v1.begin(), v1.end(), v2.begin());

(lub odwrotnie)?

+4

Operator przypisania zrobi to, co trzeba. Sposób, w jaki napisałeś 'copy', zepsuje, jeśli' v1' jest większy niż 'v2'. – jrok

+4

Jeśli 'v1' nie jest wymagany po kopii, mógłbyś po prostu' v2.swap (v1); '. – hmjd

+1

Napisz, co chcesz zrobić. Jeśli chcesz przypisać jeden wektor do drugiego, napisz to. –

Odpowiedz

46

Generalnie chciałbym zdecydowanie preferują v2 = v1:

  1. Jest krótszy i sprawia, że ​​zamierza bardziej jasne
  2. std::copy nie będzie działać, jeśli v2 nie mieć taką samą długość jak v1 (nie będzie zmień rozmiar, aby zachować niektóre stare elementy najlepiej (v2.size() > v1.size() i zastąp niektóre losowe dane używane w najgorszym przypadku w programie
  3. Jeśli v1 wkrótce wygaśnie (i użyjesz C++ 11), możesz łatwo modyfikować to do move zawartość
  4. Prawdopodobieństwo przypisania jest mało prawdopodobne niż std::copy, ponieważ implementatorzy prawdopodobnie używaliby wewnętrznie std::copy, jeśli przyniosłyby korzyści związane z wydajnością.

Podsumowując, std::copy jest mniej ekspresyjny, może zrobić coś niewłaściwego i nie jest jeszcze szybszy. Tak naprawdę nie ma powodu, aby go tu używać.

+6

Co to jest "std :: copy"? – altroware

+12

@altroware: Jest to ogólne kopiowanie z jednego zakresu do drugiego. Nie możesz, na przykład, użyć operatora przypisania do skopiowania z 'std :: list' do' std :: vector' lub z jednej części 'std :: vector' do innej części tego samego' std :: vector'. –

+0

Co się stanie, jeśli v1 zostanie przydzielony na stos i zostanie zniszczony? Czy 'v2 = v1' powoduje kopiowanie elementów v1? –

2

Jest krótszy.

std::copy jest przeznaczony głównie do kopiowania sekcji kontenerów. Jeśli chcesz skopiować cały kontener, równie dobrze możesz użyć konstruktora kopiowania.

+0

Jeśli 'v2' nie jest wystarczająco duży, dostaniesz przepełnienie bufora. –

9

Wywołanie std::copy może próbować uzyskać dostęp do elementów poza końcem wektora docelowego.

Użyj przypisania.

Nie należy do ciebie mikrooptymalizacja: to odpowiedzialność autora biblioteki, a ostatecznie odpowiedzialność kompilatora.

Możesz ustawić kod dowolnie szybko, jeśli nie musi być poprawny.

Jednak w przypadku modelu copy raczej wątpliwe jest, czy jest ono jeszcze szybsze, a z pewnością nie jest poprawne w przypadku ogólnym.

+3

Zgadzam się z Twoimi stwierdzeniami dotyczącymi optymalizacji, ale warto zauważyć, że im więcej informacji jest dostępnych dla kompilatora lub biblioteki, tym lepiej może wykonywać swoją pracę. Funkcje członkowskie 'std :: vector' wiedzą, że pracują nad' std :: vector' i wiedzą, w jaki sposób jest on implementowany. 'std :: copy' nie ma tych informacji. Wniosek jest taki, że funkcje członka mogą prawdopodobnie lepiej wykonywać tę pracę (a już na pewno nie gorzej). –

2

Zadanie, jak dotąd. Mówiąc ogólniej, za każdym razem, gdy wielkość wektora może się zmieniać lub zmieniać całą zawartość wektora, powinieneś preferować funkcje członka. Jedyny przypadek, gdy std::copy byłby odpowiedni, to jeśli zastępujesz tylko mały zakres całkowicie w obrębie wektora.

6

Jeśli v2 nie jest wystarczająco duży, otrzymasz przepełnienie bufora, jeśli używasz copy, tak jak masz.

Można użyć iteratora z tylną wstawką, który wywoła funkcję push_back na v2. Może to jednak prowadzić do wielokrotnych ponownych przydziałów w zależności od tego, jak duży jest v1.

copy(v1.begin(), v1.end(), back_inserter(v2)); 

Lepiej pozwolić, aby vector poprawnie zarządzać rzeczami. Operator przypisania robi to, co robi vector::assign:

v2.assign(v1.begin(), v1.end()); 

Mam przeczucie, że operator przypisania jest realizowany pod względem vector::assign.

+0

Panie Wood, czy to możliwe, że chodziło o v2.assign (v1.begin(), v1.end()) zamiast v2.assign (v1.begin(), v2.end())? –

+0

@PeterSchaeffer naprawiony, dzięki –

1

Przypisanie jest bardziej wyraźne i wewnętrznie wykorzystuje (lub unitizalized_copy_M_allocate_and_copy zależnie od rozmiaru i pojemności), więc wydajność jest taka sama.

Powiązane problemy