2010-02-07 14 views
1

Je Couchait avec C++ et références const et suis confus pourquoi ce code fonctionne:Pourquoi cela fonctionne-t-il? De retour références const en C++

#include <iostream> 

class A { 
public: 
    A() : a_(50) {} 
    const int& getA() const { return a_; } 
private: 
    const int a_; 
}; 

int main(int argc, char* argv[]) 
{ 
    A* a = new A(); 
    const int& var = a->getA(); 
    std::cout << var << std::endl; 
    delete a; 
    std::cout << var << std::endl; 
} 

Résultat:

50 
50 

Voici mes pensées:

var stocke une référence à a_.
lorsqu'un a est supprimé, a_ doit également être supprimé.
Lorsque var est à nouveau accédé, il ne contient plus de référence valide et une erreur de segmentation doit se produire.

Pourquoi cela fonctionne-t-il? Je ne crois pas que je fasse une copie temporaire.

Répondre

13

Au moment où vous avez supprimé a, l'accès à var est devenu votre porte d'entrée dans undefined behavior land.

Ça "marche" par hasard. L'espace où l'on faisait référence à var n'est plus le vôtre, mais vous vous en êtes sorti avec l'accès, cette fois. Cela aurait pu entraîner une erreur de segmentation, renvoyé un nombre autre que 50 ou reformaté votre disque dur. Rappelez-vous, le fait de travailler semble être un comportement possible qui peut se manifester.

+0

C'était ma meilleure estimation - cela fonctionne dans ce cas, mais il a un comportement indéfini. Il n'est certainement pas garanti de travailler et est très dangereux. – devillighter

+0

Pire - un de ces bogues qui se comportera différemment dans le débogage/la libération et sur les CPU simples/dual core –

3

La suppression d'un objet n'efface pas la mémoire. La valeur sera toujours là jusqu'à ce que la mémoire soit utilisée pour autre chose. Cela peut donc fonctionner pendant un certain temps ....

Certaines implémentations C++ ont un "mode de débogage" qui définit une valeur particulière pour toute la mémoire supprimée afin de détecter les bogues comme celui-ci.

2

Lorsque vous supprimez un, vous libérez de la mémoire et vous en autorisez une nouvelle à la surcharger. Jusque-là toutes les variables à l'intérieur de votre objet supprimé sont toujours en mémoire, mais peuvent être remplacées à tout moment.

1

Ceci est assez difficile en raison du mot-clé const.

True, vous pourriez lire la mémoire non initialisée dans ce cas. Quelques réflexions sur ce point:

  1. Vous n'êtes pas utiliser le mode de débogage: ce qui est généralement pas une bonne idée aussi longtemps que le code n'a pas été testé, mais il laisse deux options:
    • La version Le gestionnaire de mémoire de mode n'écrase pas la mémoire, donc vous acces la dernière adresse connue, qui fonctionne toujours par hasard
    • OU L'opération entière est complètement optimisée parce que le compilateur sait que vous n'avez pas changé la valeur et il n'a pas pu changer de l'extérieur (bien que cela puisse ne pas être vrai en raison des limitations de const correction en C++)
  2. Vous êtes en mode débogage, mais ont des optimisations activées, de sorte que le même argument vaut
  3. Le contenu de _a, car marqué const ne sont pas tas alloués ni pile alloué, mais résident dans la partie DATA de l'application, donc la référence pourrait en effet être toujours valable, pas seulement par hasard. [EDIT]: Cela ne peut être vrai que pour les variables static const.

Vous pourriez envisager d'écrire un gestionnaire de mémoire personnalisé ou de faire des recherches sur le comportement du mode de débogage de votre compilateur, car c'est très, très important. Visual Studio va définir des variables à 0xCDCDCDCD, par exemple. Vous trouverez également des valeurs amusantes telles que 0xDEADC0DE à la fin des tableaux.

+0

En ce qui concerne (3), la seule façon dont '_a' pourrait être dans la section DATA serait si le compilateur effectuait analyse statique approfondie et a déterminé qu'il n'y avait jamais qu'une seule instance de 'A', auquel cas l'objet entier serait là. Un membre 'const' occupe toujours de l'espace dans chaque instance d'un objet. –

+0

très vrai ... Edité ma réponse en conséquence. Merci de me corriger. – mnemosyn

+0

Ouais, je me demandais si vous pensiez à const statique. +1 –