Domanda

Perché questo:

#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;
}

Dare uscita:

  

La risposta è:

Al posto di:

  

La risposta è: quattro

È stato utile?

Soluzione

Solo locale riferimenti const prolungare la durata della vita.

Il previsto dalla norma tale comportamento in §8.5.3 / 5, [dcl.init.ref], la sezione inizializzatori di dichiarazione riferimento. Il riferimento nel tuo esempio è destinato a n argomento del costruttore e non è più valido quando l'n oggetto è destinato a va fuori del campo di applicazione.

La durata di vita non è transitiva attraverso un argomento di funzione. §12.2 / 5 [class.temporary]:

  

Il secondo contesto è quando un riferimento si associa a un temporaneo. La temporanea in cui è vincolato il riferimento o la temporanea che è l'oggetto completa ad un sotto-oggetto di cui il temporaneo è vincolato persiste per la durata del riferimento eccetto come in appresso. Un temporaneo legato ad un organo di riferimento in ctor-inizializzatore di un costruttore (§12.6.2 [class.base.init]) persiste fino al uscite costruttore. Un temporaneo legato ad un parametro di riferimento in una chiamata di funzione (§5.2.2 [expr.call]) persiste fino al completamento della piena espressione contenente la chiamata.

Altri suggerimenti

Ecco il modo più semplice per spiegare cosa è successo:

In main () ti ha creato una stringa e la passò al costruttore. Questa istanza stringa esisteva solo all'interno del costruttore. All'interno del costruttore, che è stato assegnato membro per puntare direttamente a questa istanza. Quando quando portata lasciò il costruttore, l'istanza stringa è stata distrutta, e poi membro indicò un oggetto stringa che non esiste più. Avente punto Sandbox.member ad un riferimento di fuori del suo campo di applicazione non terrà quei casi esterni portata.

Se si vuole risolvere il tuo programma per visualizzare il comportamento desiderato, apportare le seguenti modifiche:

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

Ora temperatura passerà fuori portata alla fine del main () invece che alla fine del costruttore. Tuttavia, questa è una cattiva pratica. La variabile membro non dovrebbe mai essere un riferimento a una variabile che esiste al di fuori dell'istanza. In pratica, non si sa mai quando tale variabile andrà fuori del campo di applicazione.

Quello che consigliamo è quello di definire Sandbox.member come const string member; Questo copierà i dati del parametro temporanea nella variabile membro invece di assegnare la variabile membro come parametro temporanea in sé.

Tecnicamente parlando, questo programma non è tenuto a realtà uscita nulla sullo standard output (che è un flusso tamponato per cominciare).

  • Il bit cout << "The answer is: " emetterà "The answer is: " nel tampone di stdout.

  • Poi il bit << sandbox.member fornirà il riferimento penzoloni in operator << (ostream &, const std::string &), che invoca comportamento indefinito .

A causa di questo, nulla è garantito per accadere. Il programma può funzionare apparentemente bene o si può bloccare senza nemmeno vampate stdout - che significa il testo "La risposta è:". Non sarebbe arrivare a comparire sullo schermo

Perché il vostro stringa temporanea è andato fuori del campo di applicazione una volta che il costruttore di Sandbox è tornato, e lo stack occupata da esso fu bonificata per altri scopi.

In generale, non si dovrebbe mai mantenere i riferimenti a lungo termine. I riferimenti sono buone per argomenti o variabili locali, mai i membri della classe.

ti riferisci a qualcosa che è scomparso. Di seguito lavorerà

#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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top