Question

Pourquoi ceci:

#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 sortie:

  

La réponse est:

Au lieu de:

  

La réponse est: quatre

Était-ce utile?

La solution

seulement références locales de const prolonger la durée de vie.

La norme spécifie un tel comportement en §8.5.3 / 5, [dcl.init.ref], la section sur initializers des déclarations de référence. La référence dans votre exemple est lié à l'argument du constructeur de n et devient invalide lorsque le n d'objet est lié à est hors de portée.

L'extension de durée de vie est pas transitive par un argument de fonction. § 12.2 / 5 [class.temporary]:

  

Le second contexte est lorsqu'une référence est lié à un temporaire. Le temporaire dans lequel la référence est lié ou temporaire qui est l'objet complet à un sous-objet, dont le temporaire est persiste à destination de la durée de vie de la référence, sauf comme indiqué ci-dessous. Un temporaire lié à un élément de référence en cteur-initialiseur d'un constructeur (§12.6.2 [class.base.init]) persiste jusqu'à ce que les sorties du constructeur. Un temporaire lié à un paramètre de référence en un appel de fonction (§5.2.2 [expr.call]) persiste jusqu'à l'achèvement de la pleine expression contenant l'appel.

Autres conseils

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

Dans main () que vous avez créé une chaîne et passée dans le constructeur. Cette instance de chaîne n'existait dans le constructeur. A l'intérieur du constructeur, vous un membre assigné à pointer directement à cette instance. Lorsque la portée lorsque le constructeur a quitté, l'instance de chaîne a été détruite, et membre alors pointé un objet de chaîne qui n'existait plus. Ayant un point Sandbox.member à une référence en dehors de son champ d'application ne sera pas tenir ces instances externes portée.

Si vous voulez fixer votre programme pour afficher le comportement que vous désirez, apportez les modifications suivantes:

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

température passera hors de portée à la fin de main () au lieu de la fin du constructeur. Cependant, cela est une mauvaise pratique. Votre variable membre ne doit jamais être une référence à une variable qui existe en dehors de l'instance. En pratique, vous ne savez jamais quand cette variable sera hors de portée.

Ce que je recommande est de définir Sandbox.member comme const string member; Cela copiera les données de paramètres temporaires dans la variable membre au lieu d'assigner la variable membre comme paramètre temporaire lui-même.

Sur le plan technique, ce programme n'a pas à quoi que ce soit réellement sortie standard (ce qui est un flux tampon pour commencer).

  • Le bit cout << "The answer is: " émettra "The answer is: " dans la tampon de stdout.

  • Le bit de << sandbox.member fournira la référence boiteuse dans operator << (ostream &, const std::string &), qui appelle comportement non défini .

En raison de cela, rien est garanti arriver. Le programme peut fonctionner en apparence bien ou peut se bloquer sans rinçage, même stdout - qui signifie que le texte « La réponse est: ». Ne s'apparaître sur votre écran

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

En général, vous ne devriez jamais retenir 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.

vous faites référence à quelque chose qui a disparu. Ce qui suit fonctionne

#include <string>
#include <iostream>

class Sandbox
{

public:
    const string member = " "; //default to whatever is the requirement
    Sandbox(const string& n) : member(n) {}//a copy is made

};

int main()
{
    Sandbox sandbox(string("four"));
    std::cout << "The answer is: " << sandbox.member << std::endl;
    return 0;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top