198 votes

Ne const référence prolonger la durée de vie temporaire?

Pourquoi est-ce que:

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

Donner de la sortie de:

La réponse est:

Au lieu de:

La réponse est: quatre

190voto

Potatoswatter Points 70305

Seulement locale, const références prolonger la durée de vie.

La norme spécifie un tel comportement dans le §8.5.3/5, [dcl.init.ref], la section sur les initialiseurs de référence déclarations. La référence dans votre exemple est lié au constructeur de l'argument n, et devient non valide lorsque l'objet n est lié au sort de la portée.

La durée de vie de l'extension n'est pas transitive par le biais d'un argument de fonction. §12.2/5 [classe.temporaire]:

Le deuxième contexte est quand une référence est lié à un emploi temporaire. La temporaire de laquelle la référence est lié ou temporaire qui est l'objet d'un sous-objet dont le temporaire est lié persiste pendant toute la durée de vie de la référence, sauf comme indiqué ci-dessous. Temporaire lié à un membre de référence dans un constructeur ctor-initialiseur (§12.6.2 [classe.de la base.init]) persiste jusqu'à ce que le constructeur sort. Temporaire lié à un paramètre de référence dans un appel de fonction (§5.2.2 [expr.appel]) persiste jusqu'à la fin de la pleine expression contenant l'appel.

32voto

Squirrelsama Points 1333

Voici la façon la plus simple d'expliquer ce qui s'est passé:

Dans main (), vous avez créé une chaîne de caractères et l'a transmis au constructeur. Cette chaîne instance n'existe que dans le constructeur. Dans le constructeur, vous avez assigné le membre à pointer directement vers cette instance. Lors de l'étendue de la gauche, le constructeur, la chaîne d'instance a été détruit, et membre souligné un objet de type string qui n'existait plus. Avoir Bac À Sable.membre de point de référence à l'extérieur de son champ d'application ne sera pas titulaire de ces instances externes dans le champ d'application.

Si vous souhaitez corriger votre programme pour afficher le comportement que vous désirez, effectuez les modifications suivantes:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

Maintenant temp de passer hors de portée à la fin de main() plutôt qu'à la fin du constructeur. Cependant, c'est une mauvaise pratique. Votre membre de la variable ne doit jamais être une référence à une variable qui existe en dehors de l'instance. Dans la pratique, vous ne savez jamais quand cette variable passe hors de portée.

Ce que je recommande est de définir bac à sable.membre en tant que const string member; Cette copie temporaire du paramètre de données dans la variable membre au lieu d'affecter la variable de membre temporaire pour le paramètre lui-même.

0voto

Fyodor Soikin Points 7907

Parce que votre chaîne temporaire est allé hors de portée une fois le bac à sable constructeur retourné, et la pile occupé par elle a été récupérée pour d'autres fins.

En général, vous ne devriez jamais conserver les références à long terme. Les références sont bonnes pour les arguments ou les variables locales, jamais les membres de la classe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X