2009-11-07 5 views
10

Je connais des conteneurs STL comme vector qui copie l'objet quand il est ajouté. méthode push_back ressemble à:Comment les conteneurs STL copient-ils des objets?

void push_back (const T& x); 

Je suis surpris de voir qu'il prend l'élément comme référence . J'ai écrit un exemple de programme pour voir comment cela fonctionne.

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); 

Cette copie l'objet et je peux le voir appelle copie constructeur.

Ma question est, quand le push_back prend l'article comme référence, comment il appelle copy-constructor? Ou est-ce que je manque quelque chose ici?

Des pensées ..?

Répondre

12

Il utilise probablement "placement new" pour construire l'objet en place dans son réseau interne. Le placement new n'alloue aucune mémoire; il place juste l'objet où vous spécifiez, et appelle le constructeur. La syntaxe est new (address) Class(constructor_arguments).

Le constructeur de copie T::T(T const &) est appelé pour créer la copie sur place. Quelque chose comme ça (simplifié):

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

Notez que T doit avoir un constructeur de copie pour que cela fonctionne. Par défaut (si vous ne faites rien), il en obtient un gratuitement. Si vous le définissez explicitement, il doit être public pour que vector<T> fonctionne.

Here's how GNU's libstdc++ does it, mais je doute que ce sera très éclairant. Il y a un allocateur (le deuxième argument de modèle à vector) qui le rend moins simple.

+0

C'est OK quand T a un constructeur sans paramètre. Mais qu'arrivera-t-il quand il aura un constructeur paramétré? Comment le vecteur peut-il initialiser un nouvel objet? –

+0

C'est OK quand T a un constructeur _copy. Ce qui est fait, par défaut, et si vous l'implémentez, à moins que vous ne l'ayez fait explicitement 'private' ou' protected'. – Thomas

+0

J'ai édité ma réponse pour clarifier. – Thomas

1

Il utilise le nouvel opérateur placement et le copie-le construit en mémoire unitialisée;

Le placement new crée un nouvel élément à une adresse spécifiée en mémoire, dans le cas du vecteur, l'extrémité actuelle();

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

regard sur http://spotep.com/dev/devector.h qui a un code tout à fait clair (par opposition à la plupart des implémentations STL).

3

Le SDK C++ prend toujours const T & comme paramètre de fonction pour l'efficacité.

Dans le cas où le paramètre prend T, l'action de copie sera effectuée deux fois, une pour la passer à la fonction push_back(f), une pour l'ajouter au conteneur. Et en prenant const T& comme paramètre, une seule copie est nécessaire!

+7

Il n'y a pas de SDK C++. – GManNickG

+0

ok, je veux dire les choses au sol comme la spécification du langage C++, STL ect ... – learner

Questions connexes