J'ai la classe suivante: et un test très simple capable de produire le problème: p> Valgrind warns sur une écriture invalide et le débogage a montré pourquoi. Alors, pourquoi est-il appelé là-bas? Je pourrais quelque peu comprendre si le destructeur était appelé premier em>, pour se débarrasser de l'objet temporaire inutile (pas qu'il a besoin de), mais j'ai utilisé ce type de correction - désormais-assignez-les pratiquement partout et jamais eu un tel problème auparavant. p> p> CorneyByTestream reçu; code> appelle le constructeur sans arguments (qui est un peu stupide car il ne peut pas faire em> rien).
reçu = fixebytestream (12); code> appelle le constructeur avec l'argument entier ... puis appelle immédiatement le destructeur sur lui-même em>, invalidez l'objet. Cela fonctionne toujours pour une raison quelconque, mais je préfère que ce ne soit pas placé dans une telle situation étrange qui jette des avertissements. P>
6 Réponses :
Votre code est quelque peu similaire à: p> seulement dans mon exemple Le fixebytestream (12) code> est attribué à
reçu code> via l'opérateur par défaut =. Notez que vous n'avez pas alloué
fixebytestream (12) code> dans le tas en utilisant
nouveau code>, mais plutôt l'attribuée dans la portée locale sans spécifier de nom pour la variable qui le tiendrait .
TEMP code> a un nom et sa portée est toute la fonction et dans votre code de test
TEMP code> n'a pas de nom, il existe une seule ligne, puis est détruit. p>
fixebytestream (12) code> Objet Vous "vu créé ne peut pas être utilisé après cette ligne car ce n'est même pas nommé VarAible. P> P>
Vous êtes sûr qu'il utilise un constructeur de copie et non l'opérateur par défaut = code>?
Il semble que vous ne comprenez pas le cycle de vie de l'objet et n'interfère pas ce code comme code Java. P>
Lorsque vous écrivez Aussi, vous n'avez pas remplacé l'opérateur = de sorte que l'objet est copié par des octets, ce qui n'est pas correct. P> fixeByTestream reçu; code> Un objet de type fixeByTestream est créé à l'aide du constructeur sans argument. Et lorsque vous écrivez
reçu = fixebytestream (12); code> Un autre objet est créé, = l'opérateur est appelé et l'objet nouvellement créé est décroissé. P>
C'est faux. L'objet précédent n'est pas désttruit, le temporaire est, après sa copie à l'objet précédent.
En outre, ce n'est qu'une coïncidence que dans ce cas opérateur = agit comme une copie bitwise. En vérité, cela invoque l'affectation sur chaque membre.
étape par étape: éditer: p> Comme je vois qu'il y a beaucoup de réponses erronées fortes> pour cette question, je vais expliquer plus en détail. Je pourrais avoir une certaine haine pour cela, mais c'est un concept assez important et j'ai bownvoché de sorte qu'une mauvaise réponse ne soit pas acceptée et prise de l'acquisition. P> Vous initialisez essentiellement un objet sur la pile . P> Je vais simplifier votre cas: P> {
A a;
{
A b;
a = b;
}
}
Les autres réponses semblent avoir été corrigées.
C'est des informations très utiles, merci pour l'explication détaillée!
objet est déjà initialisé sur cette ligne sur la ligne p> vous le réinitialisez-le. La bonne façon de le faire est la suivante: p> (je vais certainement aller pour la première) p> p>
Malheureusement, le premier n'est pas possible, car dans la pratique i> la taille n'est pas connu au moment de la création d'objets (problème de portée). La seconde fonctionnera probablement, mais je dois vraiment configurer le constructeur de copie et l'opérateur d'affectation de toute façon.
Il vous manque un opérateur d'affectation. Rappelez-vous le règle de trois (ou cinq).
Le problème est à peu près comme ceci: p> Vous ne fournissez aucun opérateur d'affectation, de sorte que la valeur du pointeur dans le temporaire est simplement copiée dans t, puis la mémoire pointée sur est supprimée dans le destructeur . p> Aussi: ne pas avoir de constructeur par défaut, si l'objet construit n'est pas valide. p> p>
Honnêtement, je ne m'attendais pas à ce que je devrais remplacer cela pour une copie triviale, merci pour l'information.
@Digitalman Votre code est fondamentalement l'exemple par défaut de la règle de trois. Mais des situations comme celle-ci sont très rares dans le code moderne C ++. Votre exemple d'usuallly serait écrit avec un vecteur code> et ce serait inutile.
@Digitalman: Vous auriez pu contourner cela de manière triviale en écrivant t t (2); code>. Qu'est-ce qui vous a donné l'idée de la diviser en deux étapes?
@Kerreksb en quelque sorte je suis content qu'il ait fait. Il a exposé un bug et lui a appris une leçon précieuse.
@Kerrek SB c'était un exemple pour reproduire le problème. Dans mon code actuel, il n'a aucune idée de la taille de la méthode fixeByTesteam doit être jusqu'à quelques niveaux plus profondément dans la portée - et pas i> avoir une taille changeante est ce qui le rend "fixe".
@Digitalman: Pourquoi ne pas le construire uniquement lorsque vous en avez besoin ou utilisez redimension () code> à l'heure appropriée?
Si votre objet a un constructeur défini par l'utilisateur, il est toujours fort> construit à l'aide d'un constructeur. Il suffit de définir un objet sans aucun argument constructeur utilise le constructeur par défaut indépendant de savoir si l'objet est écrasé par la suite. C'est FixedByteStream& FixedByteStream::operator= (FixedByteStream& other) {
this->existing = other.existing;
this->size = other.size;
this->address = other.address;
return *this;
}
Pas nécessairement votre problème, mais vous devez ajouter un constructeur de copie. Le constructeur de copie actuelle finira par faire duping le pointeur - de sorte que le destructeur appelé d'abord supprimera la mémoire d'un autre objet.
@Tanycorn dans ce cas exacte, il a besoin d'un opérateur d'affectation
à droite - manquait cette partie - c'est juste quelque chose qui s'en tient vraiment