Passando per riferimento

0

Sto cercando di capire le idee di puntatori e riferimenti in C ++. Sono bloccato con quanto segue, quale sarebbe il comportamento specifico in questo caso? Ho una classe come questa:

class MyClass{
public:
     MyClass(const QByteArray & raw){
        this->m_rawData =raw;
     }
private:
   QByteArray m_rawData;
}

Diciamo che creo l'istanza in questo modo:

bool otherClass::someOtherMethod(){
    QByteArray data = QString("sometext").toUtf8();
    MyClass instance = new MyClass(data);
    return true;
}

Trasmetto l'indirizzo della variabile data al costruttore della mia classe, quindi esco dal metodo locale di OtherClass . Il QByteArray data verrà distrutto e la sua memoria liberata, giusto? Ma cosa succederà in MyClass instance ? Questo sarà

 MyClass(const QByteArray & raw){
            this->m_rawData =raw;
         }

copia effettivamente il contenuto di raw in m_rawData o copierà il riferimento effettivo del grezzo e m_rawData diventerà non valido quando restituisce otherClass::someOtherMethod ?

    
posta Vlad 08.07.2016 - 17:18
fonte

2 risposte

5

Sotto il cofano, potrebbe essere implementato in modo diverso, ma l'effetto visibile di

MyClass(const QByteArray & raw){
        this->m_rawData =raw;
}

sarà il contenuto di raw copiato in m_rawData e sopravviverà dopo che raw è stato distrutto.

Funziona perché m_rawData è dichiarato come valore di tipo QByteArray . Se fosse stato un puntatore o un riferimento, sarebbe stato lasciato penzolare se raw è stato distrutto prima di m_rawData .

Una cosa importante da ricordare in C ++ è che tutto è un valore a meno che tu non lo renda esplicitamente un puntatore o un riferimento.

    
risposta data 17.07.2016 - 13:08
fonte
0

... copy the content of raw into m_rawData or it will copy the actual reference of the raw and m_rawData will become invalid when the otherClass::someOtherMethod returns?

this->m_rawData =raw;

probabilmente innescherà l'operatore di assegnazione delle copie su QByteArray. Questo perché non hai inizializzato m_rawData nel blocco di inizializzazione e quindi hai probabilmente chiamato il costruttore predefinito su QByteArray per inizializzare m_rawData. Dopo ciò è accaduto, in the ctor, l'assegnazione del contenuto dei dati a m_rawData tramite l'assegnazione della copia.

L'operatore di assegnazione copie predefinito è probabilmente:

QByteArray &operator=(const QByteArray& other) {
  return *this;
}

che assegna valori in altro a questo. Tuttavia, l'operatore di assegnazione generato dal compilatore probabilmente restituisce probabilmente un puntatore che lascia tutti i valori in QByteArray come dati inutili in cui nulla viene effettivamente copiato. (Questa è una buona ragione per "cancellare" in pratica tutti i metodi della classe generata dal compilatore)

Per risolvere questo problema è necessario un operatore di assegnazione copia valido su QByteArray.

Anche questo:

bool otherClass::someOtherMethod(){
    QByteArray data = QString("sometext").toUtf8();
    MyClass instance = new MyClass(data);  // leak!
    return true;
}  

La memoria dovrebbe essere di proprietà. Se insisti sulla memoria dinamica fai questo:

bool otherClass::someOtherMethod(){
    QByteArray data = QString("sometext").toUtf8();
    std::unique_ptr<MyClass> fixed(new MyClass(data));
    return true;
}

So the QByteArray data will be destroyed and its memory freed right?

Una volta che la variabile dello stack originale "data" esce dall'ambito, attiverà il suo distruttore.

    
risposta data 25.07.2016 - 18:49
fonte

Leggi altre domande sui tag