web-dev-qa-db-fra.com

Pourquoi C ++ ne nécessite-t-il pas une "nouvelle" instruction pour initialiser std :: vector?

/* bar.h */
class bar{
    /* standard stuff omitted */
    std::vector<my_obj*> foo;
};

/* bar.cpp */
bar::bar(){ 
    // foo = new std::vector<my_obj*>(); <-- why don't I need this line??
    foo.Push_back(new my_obj());
}

Pourquoi ce code fonctionne-t-il alors que nous n'avons pas assigné à foo une nouvelle instance de std :: vector?

31
ash

Parce que C++ n'est pas C #/Java.

std::vector<my_obj*> foo;

Ceci est une définition d'un objet, pas une référence comme en C #/Java. Un objet est une instance vivante d'un type.

new std::vector<my_obj*>()

Cette expression renvoie un pointeur. Il renvoie un std::vector<my_obj*>*, qui est pas du même type que foo (le * à la fin est ce qui les rend différents). foo est un objet, std::vector<my_obj*>* est un pointeur sur un objet.

Les objets (plutôt que les pointeurs ou les références) ont des durées de vie spécifiques. Si vous créez un pointeur sur un objet avec new, la durée de vie de l'objet pointé sera jusqu'à ce que vous appeliez explicitement delete. Si vous créez un objet en tant que membre d'un autre objet, la durée de vie de cet objet interne reflétera (plus ou moins) la durée de vie de l'objet externe. Si vous créez un objet sur la pile (un paramètre ou une variable à la portée de la fonction), sa durée de vie est la portée actuelle de ce nom de variable.

46
Nicol Bolas

Parce que bar contient un std::vector, pas un std::vector *.

Ce n'est vraiment pas différent de quelque chose comme ça:

class bar
{
    int foo;  // No need to create a "new int"
};
6
Oliver Charlesworth

Parce que foo est un objet et non un pointeur.

std::vector<my_obj*>    // This is an object
std::vector<my_obj*> *  // This is a pointer to an object
                    ^^^ // Notice the extra star.

Nouveau retourne un pointeur:

new std::vector<my_obj*>();  // returns std::vector<my_obj*> *

PS. Votre vecteur doit probablement contenir des objets et non des pointeurs.

std::vector<my_obj>   foo;
...
foo.Push_back(my_obj());

Sinon, vous devrez supprimer manuellement tous les objets du vecteur lorsqu'il sort de la portée (lorsque l'objet contenant est détruit). Par exemple, si vous souhaitez conserver des pointeurs dans votre vecteur, vous devez effectuer l'une des opérations suivantes:

// 1. Manually delete all the elements in the vector when the object is destroyed.
~bar::bar()
{
    for(std::vector<my_obj*>::iterator loop = foo.begin(); loop != foo.end(); ++loop)
    {
        delete (*loop);
    }
}

// 2. Use a smart pointer:
std::vector<std::shared_ptr<my_obj> >  foo;

// 3. Use a smart container for pointers
boost::ptr_vector<my_obj>   foo
5
Martin York

Car std::vector fait ça pour vous :) Vous n'avez pas de pointeur vers std::vector, vous configurez simplement un objet de type std::vector, qui vous alloue de la mémoire en interne.

3
ScarletAmaranth

std :: vector dans cette bibliothèque n'est pas un pointeur

1
AAlkhabbaz

Vous n'avez pas besoin d'utiliser new sur foo, car foo est un vector, pas un pointeur vers un vector (c'est-à-dire std::vector<my_obj*> *foo).

Si vous venez de Java ou C #, vous pouvez envisager d'utiliser std::vector<my_obj> (un vecteur d'objets) au lieu d'un vecteur de pointeurs. Cela dépend vraiment de ce que vous voulez faire.

1
crashmstr

std::vector<my_obj *> foo est différent de std::vector<my_obj *> *foo. Le deuxième cas vous obligera à utiliser new tandis que le premier ne le sera pas.

0
Pavan Yalamanchili