9
votes

Des objets de transaction stockés dans un vecteur?

J'ai une classe qui crée un vecteur d'objets. Dans le déconstructeur de cette classe, j'essaie de distribuer la mémoire attribuée aux objets. J'essaie de le faire en bouclant juste à travers le vecteur. Donc, si le vecteur est appelé Cartes, je fais:

Building::~Building() {
    int i;
    for (i=0; i<maps.size(); i++) {
        delete[] &maps[i];
    }
}


10 commentaires

Quel est le type du vecteur ? De ce à quoi on dirait, votre vecteur contient objets , pas pointeurs des objets . Si tel est le cas, alors vous ne les supprimez pas; Le vecteur prend soin de tout le nettoyage. [Bien sûr, il est difficile de dire parce que ce code n'est pas exactement le code que vous utilisez, car taille est une fonction de membre, pas une variable de membre; Ce code ne fonctionnerait pas du tout.]


Comment ressemblent votre déclaration de vecteur et, plus important: pourquoi voulez-vous faire cela?


Tu veux dire stdd :: vecteur ou voulez-vous dire "vecteur" comme un nom alternatif pour le tableau?


Bien que la syntaxe soit fausse (paranthèses manquantes), il utilise taille , alors je suppose qu'il parle vraiment de std :: vecteur .


Oui, je parle de std :: vecteur. Et vous avez raison, j'ai besoin d'ajouter les parenthèses.


Montrez-nous la déclaration de vecteur


Etant donné que .Size () Le type de retour est Taille_t , préférez utiliser Taille_t comme type de variable d'index (ici i i ). Sauf si bien sûr que vous utilisez C ++ 0X, où vous pouvez utiliser auto . Préfère également limiter la portée de 'i` à aussi locale que possible, par exemple. Seulement à l'intérieur pour boucle. Enfin, choisissez un nom de variable différent, car ceux qui ne voyent pas la déclaration, peuvent supposer de manière incorrecte que mapper est une pluralité de std :: map .


Je voudrais mettre l'accent sur l'utilisation d'itérateurs ici tout en boucle sur le conteneur qui a été nommé carte dans la question, dans ce cas, les cartes peuvent indiquer n'importe quel conteneur mais le code destructeur reste le même.


@BLCARMADILLO - Ajout à ce que ARUN a mentionné, je voudrais également "insérer" la variable itératrice i dans la déclaration pour (taille_t i = 0; i


Si vous ne devez pas appeler "Supprimer" sur n'importe quel objet dépend de la question de savoir si l'objet existe sur le tas ou la pile. Vous devez décider où la mémoire de cet objet est allouée. Lorsque vous faites quelque chose comme MyClass * MyClass = Nouveau MyClass (...), vous avez créé le pointeur à la classe dont la mémoire a été allouée sur le tas. Les destructeurs des objets sur le tas ne seront pas appelés quand il "dépasse de la portée". Pour les objets sur la pile, les destructeurs seront automatiquement appelés. Donc, tout dépend de la façon dont les objets que vous poussez sur le vecteur ont été créés.


7 Réponses :


-2
votes

Si vous utilisez std :: vecteur alors vous pouvez simplement le laisser être manipulé par le destructeur pour vecteur , en supposant qu'il existe des "objets" (et non des pointeurs aux objets) dans ledit vecteur .

- ou -

Si vous utilisez un tableau standard comme " vecteur ":

Le but de la variation " Suppr [] " est de réexaminer une matrice complète et évitez donc de disposer de la nécessité d'avoir un pour boucle comme vous le faites.

Si vous utilisez des tableaux C / C ++ standard, " Supprimer [] mappes " devrait le faire pour vous. " [] " ne doit pas être utilisé pour compenser la location de stl vecteur s.


2 commentaires

-1 parce qu'il ne parle pas vraiment de tableaux ici. Supprimer un STD :: Vecteur de cette façon est vraiment une mauvaise idée, à part ne pas être applicable. Après la modification, toujours -1 pour suggérer d'appeler manuellement le destructeur - qui est également une mauvaise idée, voir comme il sera probablement appelé à nouveau lorsque l'objet sort de la portée. Le vecteur peut être vidé via swap si nécessaire, mais même cela est rarement nécessaire.


Vous avez raison, je ne voulais pas suggérer d'appeler explicitement le destructeur.



21
votes

Cela dépend de la manière dont le vecteur est défini.

Si des cartes est un vecteur vous supprimez chaque élément avec quelque chose de similaire à: xxx

si des cartes est un vecteur Je ne pense pas que vous devez supprimer les éléments individuels.


2 commentaires

Ce n'est que la moitié de l'histoire. Vous pouvez allouer le pointeur comme vous le dites, mais vous le faites toujours mal. C'est la poussée de ce que je recevais à mon post. Certainement, vous êtes correct, mais la compréhension des types est la partie facile (il a déjà compris la moitié de celle-ci) car le compilateur vous dit. Il me semble qu'il a une légère incompréhension des principes fondamentaux de la gestion de la mémoire.


J'ai essayé ceci mais après avoir supprimé Vec [i], la taille de vecteur est toujours identique et l'objet est là.



6
votes

en C ++, vous ne pouvez supprimer que des données par pointeur. Vous avez accompli cela à l'aide de l'opérateur & opérateur, mais si votre vecteur ne contient pas de pointeurs qui indiquent la mémoire allouée sur le tas de machines (pas la pile, de même que la méthode lorsque vous avez une déclaration de variable normale), vous pouvez essayer de Supprimez-le, mais vous rencontrerez un comportement indéfini (qui saura causer un crash de programme).

Lorsque vous insérez dans un vecteur, le vecteur appelle le constructeur de copie de la classe et vous insérez réellement une copie de l'objet. Si vous avez une fonction dont le seul but est comme suit: p> xxx pré>

se rend compte qu'il y a deux em> obj dans cette lunette: celle que vous avez passée en référence, et la copie dans le vecteur. Si nous avons eu lieu à la place de MyObject par valeur et non par référence, nous pourrions dire que deux copies de l'objet existent dans cette portée et une existence dans l'appelant. Dans chacune de ces 3 instances, ils sont pas em> le même objet. P>

Si vous stockez plutôt des pointeurs dans le conteneur, le vecteur créera une copie du pointeur ( pas em> une copie de l'objet) et insérera le pointeur copié dans le vecteur. Ce n'est généralement pas une bonne pratique d'insérer des éléments dans un conteneur par pointeur, à moins que vous ne em> ne connaisse em> que l'objet vivra au moins jusqu'à ce que le conteneur soit effectué. Par exemple, p>

void insert()
{
  Obj myObj;
  myVector.insert(&myObj);
}


0 commentaires

18
votes

Il est difficile de dire à la terminologie que vous avez utilisée et que le code présenté exactement ce qui se passe. Donc, peut-être que quelques exemples vous aideraient à sortir.

Array Nouveau et matrice Supprimer h2>

Quoi de neuf avec Nouveau [] code> et Suppr [] code> vous interroger? Ces gars sont utilisés pour allouer / distribuer des tableaux de choses. Ces choses pourraient être une pod ou ils pourraient être des objets pleins foutus. Pour les objets, ils appelleront le constructeur après l'allocation et la destructeur tout en traçant. P>

Prenons un exemple artificiel: P>

for (size_t idx = 0; idx < a_vector_of_pointers.size(); idx++) {
   delete a_vector_of_pointers[idx];
}


1 commentaires

@Eric Rahm +1 pour la réponse bonne et complète - mais je pense qu'il convient de mentionner ici que tout ce qui concerne que la suppression de la matrice d'objets ne fonctionne pas dans le cas où la matrice est de certaines catégories dérivées et le pointeur à Le tableau est de type de base. Voir la réponse ici: Stackoverflow.com/a/6171991/1971003



0
votes

Il est difficile de dire de votre question juste quelle est la signature de mapper code> est. Je suppose que vous souhaitez utiliser Suppr [] code> car vous avez également utilisé nouveau [] code>. Cela signifie-t-il que les membres de votre vecteur sont eux-mêmes une collection? Supposant que ce soit, alors vous avez quelque chose comme ceci:

class Building {
  public:
    typedef std::vector<int> maps_t;
  private:
    std::vector<maps_t> maps;
  public:
    Building();
};

Building::Building(size_t num_maps) {
  for(;num_maps; --num_maps)
  {
    maps.push_back(Building::maps_t(10));  
  }
}


1 commentaires

Peut vouloir mentionner que le "rarement" que vous faites référence serait par exemple. où la pile n'est tout simplement pas assez grosse pour que les données que vous devez contiennent.



1
votes
for(std::vector<MyObjectClass>::iterator beg = myVector->begin(), end = myVector->end(); beg != end; beg++)
{
    delete *beg;
}
myVector->clear();

0 commentaires

1
votes

J'ai décidé de transformer mon commentaire en une réponse (avec les autres grandes réponses ici), alors c'est ici.

Je remarquerais à nouveau que cette affaire traite de l'héritage de l'objet. P> Lorsque vous supprimez une matrice d'objet dérivé, indiquée par un pointeur de base, comme suit: p> xxx pré>

ce que le compilateur "sous la hotte" est de générer le code suivant : P>

#include <iostream>
using namespace std;

class Base 
{

    public:
        Base(int a, int b)
        : m_a(a)
        , m_b(b)    
        {
           cout << "Base::Base - setting m_a:" << m_a << " m_b:" << m_b << endl;
        }

        virtual ~Base()
        {
            cout << "Base::~Base" << endl;
        }

        protected:
            int m_a;
            int m_b;
};


class Derived : public Base
{
    public:
    Derived() 
    : Base(1, 2) , m_c(3)   
    {

    }

    virtual ~Derived()
    {
        cout << "Derived::Derived" << endl;
    }

    private:    
    int m_c;
};

int main(int argc, char** argv)
{
    // create an array of Derived object and point them with a Base pointer
    Base* pArr = new Derived [3];

    // now go ahead and delete the array using the "usual" delete notation for an array
    delete [] pArr;

    return 0;
}


0 commentaires