Pourquoi la mémoire est toujours accessible après std::map::clear() est appelée?
J'observe un comportement étrange de std::map::clear(). Cette méthode est censée appeler l'élément destructeur lorsqu'il est appelé, cependant le souvenir est encore accessible après l'appel à clear().
Par exemple:
struct A
{
~A() { x = 0; }
int x;
};
int main( void )
{
std::map< int, A * > my_map;
A *a = new A();
a->x = 5;
my_map.insert( std::make_pair< int, *A >( 0, a ) );
//addresses will be the same, will print 5
std::cout << a << " " << my_map[0] << " " << my_map[0]->x << std::endl;
my_map.clear();
//will be 0
std::cout << a->x << std::endl;
return 0;
}
La question est, pourquoi est variable a
toujours accessible après son destructeur est appelé par carte::clear()? Dois-je écrire delete a;
après l'appel de my_map.clear()
ou est-il sûr d'écraser le contenu de a
?
Merci d'avance pour votre aide,
sneg
- Essayez d'utiliser à() pour y accéder ne vous permettront pas d'accéder à quelque chose qui n'existe pas pour l'exemple: ideone.com/ZeRTnd (si l'élément avec la touche "B" a été défini avant, après la carte.clear() pour accéder à la touche "B" vous permet de vous
'std::out_of_range'
exception
Vous devez vous connecter pour publier un commentaire.
std::map ne gère pas la mémoire pointé par le pointeur valeurs - c'est à vous de le faire vous-même. Si vous ne voulez pas utiliser les pointeurs intelligents, vous pouvez écrire un usage général, libre & désactivez la fonction comme ceci:
Et de l'utiliser:
;
Si vous stocker des pointeurs sur une carte (ou une liste, ou quelque chose comme ça) VOUS sont responsables de la suppression de l'pointeurs, puisque la carte ne sais pas si ils ont été créés avec le nouveau, ou pas. La fonction clear seulement invoque les destructeurs si vous n'utilisez pas les pointeurs.
Oh, et encore une chose: en invoquant un destructeur (ou même l'appel de supprimer) ne signifie pas que la mémoire ne peut pas être plus accessible. Cela signifie seulement que vous aurez accès à ordures si vous n'.
C'est parce que
map.clear()
appels destructeurs des données contenues dans la carte, dans votre cas, le pointeur dea
. Et ce n'est rien.Vous pourriez mettre une sorte de pointeur intelligent dans la carte de la mémoire occupée par
a
être automatiquement récupéré.BTW, pourquoi mettez-vous le modèle arguments dans l'appel à
make_pair
? L'argument de modèle déduction doit faire assez bien ici.delete
chaque élément? Comment puis-je effacer la carte après que? Je veux dire,clear()
essaiera d'appeler les destructeurs des éléments qui ont déjà été supprimés.struct A
t appelée. I. e. élémentx
est mis à 0. Je craignais que si je supprime cette instance destruct A
carte.clear() essaie d'appeler le destructeur de nouveau.Lorsque vous libre un morceau de mémoire dans la mémoire, son contenu n'obtenez pas remis à zéro. Ils sont seulement disponible pour l'attribution de nouveau. Bien sûr, vous devriez envisager la mémoire non accessible, parce que les effets de l'accès à la mémoire non ne sont pas définis.
Effectivement empêcher l'accès à une page de la mémoire qui se passe à un niveau inférieur, et les mst bibliothèques ne pas le faire.
Lorsque vous allouer de la mémoire à nouveau, vous devez les supprimer vous-même, sauf si vous utilisez un pointeur intelligent.
Tout conteneur des magasins de votre Type d'objet et l'appel correspondant constructeurs: code interne de chaque nœud peut ressembler à:
Lorsque vous allouez il se passe par la construction de la val basés sur le type et puis de la liaison. Quelque chose de similaire à:
Lorsque vous supprimer des appels correspondant destructeurs.
Lorsque vous stockez des références (pointeurs), cela n'appelle pas de tout constructeur, ni qu'il va détruire.
Avoir passé les 2 derniers mois, l'alimentation, le sommeil, la respiration et les cartes, j'ai une recommandation. Laissez la carte d'allouer ses propres données chaque fois que possible. C'est beaucoup plus propre, pour exactement le genre de raisons pour lesquelles vous êtes mettant en évidence ici.
Il y a aussi quelques subtiles avantages, comme si vous copiez des données à partir d'un fichier ou d'un socket de la carte de données, le stockage de données existe dès que le nœud existe parce que quand la carte des appels à malloc() pour allouer le nœud, il alloue de la mémoire pour à la fois la clé et les données. (AKA carte[key].la première et la carte[key].la seconde)
Cela vous permet d'utiliser l'opérateur d'affectation au lieu de memcpy(), et nécessite 1 moins appel à malloc() - celui que vous faites.
Quelques mises en garde d'être au courant de l'méritent d'être soulignés ici.
donner une certaine pensée de l'endroit où le "point d'ancrage" de vos cartes. C'est à dire: où elles sont déclarées. Vous ne voulez pas aller en dehors de la portée par erreur. main{} est toujours en sécurité.
J'ai eu de très bonne chance, et je suis très heureux d'avoir une critique de la carte d'allouer une structure du nœud de données, et d'avoir cette structure de "point d'ancrage" une carte. Alors que les anonymes, les structures ont été abandonnés par le C++ (un horrible, horrible décision qui devait être renversée), les cartes sont la 1ère struct membre fonctionnent de la même façon anonyme des structures. Très lisse et propre avec une taille de zéro effets. En passant un pointeur vers la feuille appartenant struct, ou une copie de la structure par valeur dans un appel de fonction, les deux fonctionnent très bien. Fortement recommandé.
vous sauver vous-même une quantité ÉNORME de la confusion et de la dactylographie, et l'utilisation typedefs pour vos cartes, comme si.
passer des références de cartes à l'aide de la définition de type et & opérateur comme dans
ULNG DestroyCustomer_callMap(CUST_SUM Summary, CDR_MAP& cdrMap, KCI_MAP& kciMap)
utiliser la fonction "auto" type de variable pour les itérateurs. Le compilateur va déterminer le type spécifié dans le reste de la boucle for() organisme de ce type de carte typedef à utiliser. C'est très propre, c'est presque de la magie!
for(auto itr = Summary.callMap.begin(); itr!= Summary.callMap.end(); ++itr) {
définir certains manifeste constantes pour améliorer le rendement .effacer et .empty() plus significatif.
if(ERASE_SUCCESSFUL == cdrMap.erase (itr->second->iGUID)) {
étant donné que les "pointeurs intelligents" sont vraiment juste de garder un nombre de références, n'oubliez pas que vous pouvez toujours garder votre propre compte de référence, un probablement dans un nettoyant, et de manière plus nette. En combinant ceci avec le n ° 5 et n ° 10 ci-dessus, vous pouvez écrire quelques belles nettoyer le code comme ceci.
l'aide d'un pointeur à accrocher sur une carte nœud qui alloue tout pour lui-même, c'est à dire: aucun utilisateur pointeurs pointant vers l'utilisateur malloc()é objets de, fonctionne bien, est potentiellement plus efficace, et la et la être utilisés pour muter les données d'un nœud sans effets secondaires dans mon expérience.
sur le même thème, par exemple un pointeur peut être utilisé très efficacement pour préserver l'état d'un nœud, comme dans
pThisCDRLeafData
ci-dessus. En la passant à une fonction qui mute/changements particulier du nœud de données est plus propre que de passer une référence à la carte et la clé nécessaire pour revenir au nœudpThisCDRLeafData
pointe.les itérateurs sont pas de la magie. Ils sont coûteux et lent, comme vous vous naviguez sur la carte pour obtenir les valeurs. Pour un plan de la tenue d'un million de valeurs, vous pouvez lire un nœud selon une clé à environ 20 millions de dollars par seconde. Avec les itérateurs c'est probablement ~ 1000 fois plus lent.
Je pense que sur le couvre pour l'instant. Sera mise à jour si l'une de ces modifications ou il y a d'autres points de vue à partager. Je suis appréciant tout particulièrement l'aide de la STL avec du code C. C'est à dire: pas une classe en vue de n'importe où. Ils n'ont tout simplement pas de sens dans le contexte, je suis en train de travailler dans, et il n'est pas un problème. Bonne chance.