2009-11-07 14 views
10

Wiem, że kontenery STL, takie jak vector, kopiują obiekt po jego dodaniu. push_back metoda wygląda następująco:W jaki sposób kontenery STL kopiują obiekty?

void push_back (const T& x); 

Jestem zaskoczony, aby zobaczyć, że zajmuje pozycję jako odniesienia. Napisałem przykładowy program, aby zobaczyć, jak to działa.

struct Foo 
{ 
    Foo() 
    { 
     std::cout << "Inside Foo constructor" << std::endl; 
    } 

    Foo(const Foo& f) 
    { 
     std::cout << "inside copy constructor" << std::endl; 
    } 
}; 

Foo f; 
std::vector<Foo> foos; 
foos.push_back(f); 

Kopiuje przedmiot i widzę, że dzwoni copy-konstruktora.

Moje pytanie brzmi, kiedy push_back przyjmuje pozycję jako referencję, w jaki sposób wywołuje ona konstruktora kopiowania? Czy może czegoś tutaj brakuje?

Jakieś myśli ..?

Odpowiedz

12

Prawdopodobnie używa "miejsca docelowego new" do skonstruowania obiektu w miejscu w jego wewnętrznej tablicy. Miejsce docelowe new nie przydziela pamięci; po prostu umieszcza obiekt w określonym miejscu i wywołuje konstruktor. Składnia to new (address) Class(constructor_arguments).

Konstruktor kopiowania T::T(T const &) jest wywoływany w celu utworzenia kopii w miejscu. Coś takiego (uproszczony):

template<T> 
void vector<T>::push_back(T const &item) { 
    // resize if necessary 
    new (&d_array[d_size++]) T(item); 
} 

Zauważ, że T musi mieć konstruktor kopiujący to zadziałało. Domyślnie (jeśli nic nie robisz), dostaje jeden za darmo. Jeśli zdefiniujesz to jawnie, musi działać public dla vector<T>.

Here's how GNU's libstdc++ does it, ale wątpię, że będzie to bardzo pouczające. Istnieje alokator (drugi argument szablonu dla vector), który czyni go mniej prostym.

+0

To jest OK, gdy T ma konstruktor bez parametrów. Ale co się stanie, gdy ma sparametryzowany konstruktor? Jak wektor może zainicjować nowy obiekt? –

+0

To jest OK, gdy T ma _copy constructor_. Który jest domyślnie i jeśli go zaimplementujesz, chyba że jawnie zrobiłeś to 'private' lub' protected'. – Thomas

+0

Edytowałem swoją odpowiedź, aby wyjaśnić. – Thomas

1

Wykorzystuje nowy operator rozmieszczenia i kopiuje go do zunifikowanej pamięci;

Nowe miejsce docelowe tworzy nowy element pod określonym adresem w pamięci, w przypadku wektorowym, bieżący koniec();

void push_back(const T& val){ 
::new (&*end()) T(val); 
[increase end] 
} 

spojrzenie na http://spotep.com/dev/devector.h który ma dość wyraźny kod (w przeciwieństwie do większości implementacji STL).

3

Zestaw SDK C++ zawsze przyjmuje jako parametr wartość const T &.

W twoim przypadku, jeśli przyjmie ona T jako parametr, akcja kopiowania zostanie wykonana dwukrotnie, jedna dla przekazania go do funkcji push_back(f), druga do wewnętrznego dodania jej do kontenera. I biorąc const T& jako parametr potrzebny jest tylko jeden egzemplarz!

+7

Nie ma pakietu SDK C++. – GManNickG

+0

OK, chodzi mi o to, że z tyłu rzeczy takie jak specyfikacja języka C++, STL ect ... – learner

Powiązane problemy