Dois-je annuler une variable membre dans le destructeur?

Pourquoi voudrait-on explicitement effacer la variable membre d’un vecteur (ou de dans un dtor (voir le code ci-dessous), quels sont les avantages de l’effacement du vecteur, même s’il sera détruit juste après la dernière ligne du code de dtor être exécuté?

class A { ~A() { values.clear(); } private: std::vector  values_; }; 

question similaire sur le code suivant:

 class B { ~B() { if (NULL != p) { delete p_; p_ = NULL; } } private: A * p_; }; 

Puisqu’il n’y a aucun moyen que le dtor soit appelé deux fois, pourquoi annuler p_ alors?

Dans la classe A , il n’y a absolument aucune raison de .clear() la variable membre de type vector dans le destructeur. Le destructeur de vector fera .clear() le vector quand il sera appelé.

En classe B , le code de nettoyage peut simplement être écrit comme suit:

 delete p_; 

Il n’est pas nécessaire de tester si p_ != NULL abord parce que delete NULL; est défini pour être un no-op. Il n’est pas non plus nécessaire de définir p_ = NULL après l’avoir delete , car il n’est plus possible d’accéder légalement à p_ après la destruction de l’object dont il est membre.

Cela dit, vous devriez rarement avoir besoin d’utiliser delete en code C ++. Vous préférerez peut-être utiliser la gestion des ressources Scope-Bound (SBRM, également appelée initialisation des acquisitions de ressources) pour gérer automatiquement la durée de vie des ressources.

Dans ce cas, vous pouvez utiliser un pointeur intelligent. boost::scoped_ptr et std::unique_ptr (de C ++ 0x) sont deux bons choix. Ni l’un ni l’autre ne devraient avoir de surcharge par rapport à l’utilisation d’un pointeur brut. En outre, ils suppriment tous les deux la génération du constructeur de copie déclaré implicitement et de l’opérateur d’affectation de copie, ce qui correspond généralement à ce que vous souhaitez lorsque vous avez une variable membre qui est un pointeur sur un object alloué de manière dynamic.

Dans votre deuxième exemple, il n’y a aucune raison de définir p_ sur null, en particulier parce que cela est fait dans le destructeur, ce qui signifie que la durée de vie de p_ se terminera immédiatement après.

De plus, il est inutile de comparer p_ à null avant d’appeler delete , puisque delete expression effectue cette vérification en interne. Dans votre exemple artificiel spécifique, le destructeur doit simplement contenir delete p_ et notant else. Non if , pas de définition de p_ sur null.

Dans le cas de p_, il n’est pas nécessaire de le définir égal à null dans le destructeur, mais il peut s’agir d’un mécanisme de défense utile. Imaginons un cas où vous avez un bogue et que quelque chose garde toujours un pointeur sur un object B après sa suppression:

S’il essaie de supprimer l’object B, p_ étant nul, la seconde suppression sera inoffensive plutôt qu’un corrupteur de tas.

S’il essaye d’appeler une méthode sur l’object B, p_ étant nul provoquera un crash immédiatement. Si p_ est toujours l’ancienne valeur, les résultats ne sont pas définis et il peut être difficile de rechercher la cause du blocage.