1
votes

Suppression de l'élément correspondant pointé par chaque élément d'un tableau de pointeur en c ++

Considérez que j'ai un tableau de pointeurs déclaré comme:

myArr[i] = myObjectInstance

Et puis j'attribue des objets par

MyObject** myArr = new MyObject*[someSize] ;

Maintenant, je voulez supprimer chaque élément pointé par chaque pointeur de ce tableau. Alors, quelle est la bonne façon de faire cela? Je ne pense pas que delete [] myArr fonctionne.


4 commentaires


std :: vector > myArr; et prenez-le à partir de là ...


La bonne façon est d'utiliser un vecteur de unique_ptr au lieu d'essayer de gérer la mémoire manuellement.


Je sais que c'est recommandé. Je ne peux pas utiliser de vecteur, et je ne peux utiliser que des tableaux et de la mémoire en plus.


5 Réponses :


1
votes

Acctualy, delete [] myArr a raison, car myArr est un objet alloué dynamiquement.

Vous devrez peut-être désallouer certains myArr [i] avant si vous faites un myArr [i] = myObjectInstance myObjectInstance est alloué dynamiquement, exemple:

for (int i = 0; i < someSize; ++i)
    delete myArr[i];

delete myArr [i]; va planter si:

MyObject m;
myArr[i] = &m;

Dans le cas où toutes les positions sont allouées dynamiquement, vous pouvez utiliser un pour libérer de la mémoire:

myArr[i] = new MyObject;


3 commentaires

Qui fuit de la mémoire pour les objets eux-mêmes


cela dépend de la manière dont ils sont alloués.


L'OP veut explicitement supprimer chaque élément pointé par chaque pointeur de ce tableau .



2
votes
for (int i = 0; i < someSize; ++i)
    delete myArr[i];
That could do the trick. However you go about it, you will have to visit each element and delete it individually, and then delete the array with delete [] myArr;.But dynamically allocating arrays can be messy business. In keeping up with SO traditions, I'm going to recommend std::vector (or whatever STL container makes sense) if you are able to use it. You would still have to individually delete all elements, but now you don't have to worry about the array itself.As mentioned in the comments to your question, if you use smart pointers to each element, then you don't have to manually delete anything.

6 commentaires

C'est exact, en supposant que myObjectInstance était un pointeur vers MyObject créé avec new . Il n'y a cependant pas besoin d'indirection supplémentaire de la référence. auto i serait suffisant.


Comment cela se compile même? myArr a une taille inconnue. J'obtiens l'attendu: erreur C2672: 'begin': aucune fonction surchargée correspondante trouvée


@sweenish vous ne pouvez pas utiliser de plage basée sur une boucle sur un tableau simple


@Kapli Vous pouvez. L'erreur est que vous ne pouvez pas l'utiliser sur un tableau alloué dynamiquement. S'il avait été sur la pile, une boucle for basée sur la plage fonctionnerait très bien. Je vais éditer. C'était un oubli.


@Jeffrey J'ai oublié qu'il s'agit d'un tableau alloué dynamiquement. Si c'était sur la pile, les boucles for basées sur la plage fonctionnent très bien.


@eerorika Depuis la copie fournie est toujours un pointeur vers la même ressource dynamique, vrai. J'ai juste l'habitude d'ajouter la référence lors de modifications directes.



2
votes

Supprimez d'abord chaque objet, puis le tableau entier:

for(int i = 0; i < someSize; i++)
{
    delete myArr[i];
}
delete[] myArr;


6 commentaires

Il va planter si MyObject m; myArr [0] = & m;


L'OP a demandé "Je veux supprimer chaque élément pointé par chaque pointeur de ce tableau.". C'est ce que fait le code ci-dessus. Je fais confiance à l'OP pour mettre l'objet alloué dyunamiquement dans la liste.


Est agréable de pointer ce cas, il peut être confus. (Ce n'est pas moi qui ai voté contre)


@Jeffrey Votre confiance ne sera pas brisée


Et si tous les éléments ne sont pas alloués dynamiquement?


Ce serait une très mauvaise idée de stocker dans le même tableau les pointeurs vers les éléments alloués dynamiquement et ceux alloués non dynamiquement. Si vous avez les deux, ayez deux tableaux, avec des noms significatifs, et supprimez les éléments du bon uniquement.



2
votes

Vous pouvez utiliser l'algorithme standard std :: for_each et l'objet fonction std :: default_delete .

Voici un programme de démonstration

std::for_each( std::reverse_iterator<A **>( p + N ), 
               std::reverse_iterator<A **>( p ), std::default_delete<A>() );

Sa sortie est

9: ~A()
8: ~A()
7: ~A()
6: ~A()
5: ~A()
4: ~A()
3: ~A()
2: ~A()
1: ~A()
0: ~A()

Si vous souhaitez supprimer les éléments du tableau dans l'ordre inverse par rapport à l'ordre de leur création, vous peut écrire

#include <iostream>
#include <memory>
#include <algorithm>

struct A
{
    static size_t i;
    A() { i++; }
    ~A() { std::cout << --i << ": ~A()\n"; }
};

size_t A::i = 0;

int main() 
{
    const size_t N = 10;

    A **p = new A *[N];

    for ( size_t i = 0; i < N; i++ )
    {
        p[i] = new A();
    }

    std::for_each( p, p + N, std::default_delete<A>() );

    delete []p;

    return 0;
}


1 commentaires

Voté à la hausse, car c'est un C ++ très moderne - ish. Mais je trouve que for_each et default_delete sont un peu avancés, alors qu'un simple for pourrait faire l'affaire. Cela dépend du style, je suppose.



1
votes

Supposons que tous les myObjectInstance sont des pointeurs vers des objets alloués au tas (sinon, voir la réponse de @ Joà £ oPaulo), et pas de new personnalisé ou delete est impliqué.

for (size_t idx = 0; idx < someSize; ++idx)
    delete myArr[idx];
delete[] myArr;

Quel est le piège potentiel?

Eh bien, il y en a beaucoup. Et si seuls certains des éléments du tableau étaient initialisés? L'autre serait dans un état indéterminé et leur suppression entraînerait un comportement indéfini.

Et si plusieurs éléments du tableau pointent vers le même objet? Ensuite, vous essayez de supprimer un objet plusieurs fois. Cela conduit également à un comportement indéfini.

Cela ne signifie pas que vous ne pouvez pas utiliser cette méthode naïve, cela vous rappelle juste quelques pré-conditions:

  1. Assurez-vous que chaque élément du tableau est initialisé sur "pointeur vers un objet alloué au tas" ou sur nullptr (la suppression de nullptr est sûre).
  2. Assurez-vous de ne pas supprimer un objet deux fois.


0 commentaires