class Example
{
    public: int i;
    Example(const Example &e)
    {
        i = e.i;
    }
    Example(int i)
    {
        this->i = i;
    }
};

int main()
{
std::vector<Example*> vec;
std::vector<Example*> newVec;

Example* ex1 = new Example(1);
Example* ex2 = new Example(2);

vec.push_back(ex1);
vec.push_back(ex2);

//newVec = vec; --> This does shallow copy

for(int i=0; i<vec.size(); ++i) // --> Deep copy
{
    Example newE(*(vec[i]));
    newVec.push_back(&newE);
}

for(int i=0; i<newVec.size(); ++i)
{
    std::cout << "\nfoobar" << newVec[i]->i << "\n";
}
}

Le code ci-dessus imprime foobar2 deux fois. Ne devrait-il pas imprimer foobar1 et foobar2? De plus, est-ce la meilleure façon de copier un vecteur contenant des objets? Je veux une copie en profondeur.

-1
Dhriti Khanna 18 août 2017 à 12:01

2 réponses

Meilleure réponse
for(int i=0; i<vec.size(); ++i) // --> Deep copy
{
    Example newE(*(vec[i]));
    newVec.push_back(&newE);
}

Dans ce code, vous faites une copie de vec[i] vers Example newE. Ensuite, vous push_back l ' adresse de newE au vecteur newVec. Ensuite, l'objet newE sort de la portée et est détruit, donc vous finissez par avoir un pointeur vers les déchets à l'intérieur de newVec.

Si vous souhaitez une copie complète du contenu vectoriel, et vous souhaitez stocker des pointeurs propriétaires vers des objets, envisagez d'utiliser vecteur de pointeurs intelligents , par exemple vector<shared_ptr<Example>>.

Dans ce cas, vous pouvez simplement copier les vecteurs avec operator=, et le nombre de références des shared_ptr sera automatiquement mis à jour.

Vous voudrez peut-être considérer aussi la conception plus simple d'avoir simplement vector<Example> (sans indirection de pointeur).

5
Mr.C64 18 août 2017 à 09:12
Example newE(*(vec[i]));
newVec.push_back(&newE);

Alloue newE sur la pile, puis pousse un pointeur vers elle dans le vecteur. newE sort de la portée à la fin de l'itération de la boucle, et vous avez juste de la chance que l'emplacement de newE ne soit pas réutilisé. Il semble que le code généré par le compilateur place les deux instances de pile au même endroit, donc vous écrasez cet emplacement avec la deuxième valeur, puis vous dé-référencez cet emplacement deux fois, lors de l'itération sur le vecteur de pointeurs .

2
midor 18 août 2017 à 09:10