C++:Lors de la création de nouveaux objets à l'intérieur d'une fonction et de le retourner comme résultat, dois-je utiliser l'opérateur new pour créer l'objet?
J'ai deux factice questions qui ont confondu moi pendant un moment. J'ai fait quelques recherches en ligne et de lire beaucoup de tutoriels c++, mais je ne trouve pas de réponses concrètes.
Dire que nous avons une classe nommée Nœud qui est un bloc de construction d'une seule liste liée.
class Node
{
int data;
Node* next;
}
Fact1: les variables locales(non statique) seront détruits à la sortie des fonctions correspondantes.
Question1: Comment sur les situations coup:
Node* func()
{
Node n;
Node* ptr=&n;
return n;
}
Sera le nœud de n être détruit? Ou alors, nous devons utiliser l'opérateur new pour créer un nœud et retourner un pointeur vers une mémoire de masse. Si les deux façons de travailler, ce qui est une meilleure approche?
Question2: Comment écrire un destructeur de la classe de nœud? (Je trouve que des questions similaires sur stackOverflow, mais ces réponses axées sur le destructeur de la liste chaînée. J'ai déjà eu ce partie. Ce que je veux, c'est exactement un destructeur pour une classe de Nœud).
---------------------------------------MERCI À VOUS TOUS! JE L'AI EU------------------------------------
Remercier tous ceux qui m'ont donné des suggestions ou de relever mes erreurs. Je crois que j'ai mes réponses. Ci-dessous une note prise par moi à partir de vos réponses, et que vraiment frapper mes confusions.
- C'est pas une bonne pratique pour le retour d'une pile, l'adresse de mémoire à partir d'une fonction puisqu'elle va conduire à des comportements indéfinis.
- Retour d'un segment de mémoire est OK, mais nous avons à prendre en charge la destruction des objets.
- Une alternative sera de retour un objet, bénéficiant du constructeur de copie.
merci pour votre réponse rapide. Je suis à la révision de la programmation en c++ et à cette question il suffit de venir dans ma tête et j'ai juste tapé le code à la volée. Je l'ai juste testé et ça ne compile pas. Une version compilée de code sont en train d'être mis à jour. Toujours les mêmes questions.
il n'est toujours pas compiler. Le type de retour de la fonction est
Node*
mais vous êtes de retour n
qui est un Node
OriginalL'auteur user3367047 | 2014-10-10
Vous devez vous connecter pour publier un commentaire.
Question 1
Votre code crée un local
Node
instance (sur la pile), puis retourne son adresse. Lorsque la fonction est de retour, leNode
exemple, une variable locale est détruite. L'adresse de la fonction renvoyée pointe désormais à la mémoire définie contenu, et à toute tentative de déréférencement du pointeur this mèneront à un comportement indéfini.Afin de créer un nœud, vous avez réellement besoin d'appeler un
Node
constructeur. Comment vous voulez retourner le résultat est pertinent pour comment vous appelez le constructeur.Vous pouvez soit retourner un pointeur que vous étiez en train de faire, dans ce cas, vous devez utiliser le
new
opérateur:Toutefois, lorsque vous faites cela, vous donner
func
les appelants de la responsabilité de détruire l'objet en question. Depuisnew
etdelete
sont symétriques, il est considéré comme une meilleure forme pour les mettre dans symétrique endroits dans votre code, comme ceci:Une meilleure alternative au total peut-être d'utiliser
std::shared_ptr
qui vous donne de comptage de référence, comme ceci:À l'aide de cette approche, les appelants n'ont pas besoin de gérer manuellement chaque nœud du cycle de vie. Une autre alternative est d'utiliser
std::unique_ptr
à la place, qui permet uniquement l'unique propriétaire de l'objet.Ou vous pouvez retourner le nœud de valeur, auquel cas vous créer localement, puis laissez-le retour de la fonction des mécanismes d'en faire une copie lorsque vous retourner:
Question 2
Vous pouvez déclarer un destructeur de ce genre dans votre
Node
déclaration de classe:Ensuite, vous pouvez le définir comme ceci:
Cependant, il est probablement mieux fait de laisser la liste gérée la connexion entre ses
Node
instances (next
champ), et ne laisse lesNode
classe de gérer le cycle de vie de ses membres des données (data
champ)OriginalL'auteur Martin J.
Vous pouvez retourne le pointeur à l'objet local, mais il sera dirigé vers la pile de la mémoire, de sorte que les résultats peuvent être surprenants. Regardez le code suivant:
Vous n'obtiendrez pas "10" "20" de sortie. Au lieu de cela
Premier objet a été détruite (lors de la première
create
appel de fonction clos). Deuxième objet a été créé sur le dessus de reutilisablen1
, doncn1
adresse est égale àn2
adresse.Compilateur va vous avertir lorsque vous retournez la pile d'adresses:
OriginalL'auteur danbst
Ce que tu ne veux sans doute dire:
Mais qui aurait conduit à un comportement indéfini, comme le
Node n
serait sur la pile et non pas sous votre contrôle.Qui pourrait fonctionner, mais vous auriez besoin de libérer la
Node*
dans votre destructeur.Si vous pouvez utiliser c++11 caractéristiques, je serais probablement aller avec un
std::unique_ptr<Node>
:De cette façon, votre Nœud d'être libéré par le destructeur de la
std::unique_ptr<>
.OriginalL'auteur Theolodis
Non, vous n'avez pas à utiliser
new
pour retourner un objet à partir d'une fonction. Vous pouvez retourner une copie d'un objet local.Q1:
Will the node n be destroyed?
MODIFIER selon le nouveau code:
Le type de retour de la fonction est le Nœud* mais vous êtes de retour n qui est un Nœud. Votre exemple ne peux pas compiler. Le local
Node n
seront détruits à la fin de la fonction, oui. Comme le font toutes les variables avec stockage automatique (non statique des locaux).Réponse selon l'ancien code:
Vous avez un
Node*
c'est à dire un pointeur. Vous essayez d'initialiser le pointeur d'entier 10, mais ça ne compile pas. Si le code à compiler, une copie du pointeur serait retourné et le pointeur est détruit à la fin de la fonction. Pas deNode
instances ont été créées. Un déréférencement du pointeur retourné aurait un comportement indéterminé, sauf si vous êtes absolument sûr que vous avez alloué unNode
instance à l'adresse mémoire que vous initialiser le pointeur (ce qui n'arrive pas dans le code).T2:
How to write a destructor for the node class?
Cela dépend de votre conception. Si la mémoire de
Node
s'est géré par une classe englobante (par exemple,List
) vous pouvez choisir de ne rien faire dansNode
's destructeur. SiNode
est responsable de la liésNode
's de la mémoire, vous devez allouer dynamiquement des instances (avecnew
) etdelete
dans le destructeur. La suppression manuelle n'est pas nécessaire si vous utilisezstd::unique_ptr
.OriginalL'auteur eerorika