3 votes

Comment fonctionne la référence C++

Après avoir travaillé 15 ans en C++, j'ai constaté que je ne comprenais pas complètement les références...

class TestClass
{
public:
    TestClass() : m\_nData(0)
    {
    }

    TestClass(int n) : m\_nData(n)
    {
    }

    ~TestClass()
    {
        cout << "destructor" << endl;
    }

    void Dump()
    {
        cout << "data = " << m\_nData << "  ptr = 0x" << hex << this << dec << endl;
    }

private:
    int m\_nData;
};

int main()
{
    cout << "main started" << endl;

    TestClass& c = TestClass();
    c.Dump();

    c = TestClass(10);
    c.Dump();

    cout << "main ended" << endl;

    return 0;
}

// prints:
// main started
// data = 0  ptr = 0x0012FF54
// destructor
// data = 10  ptr = 0x0012FF54
// main ended
// destructor

Je comprends de ce test que l'instance de TestClass est créée sur la pile (est-ce correct ?) et initialisée par le premier constructeur de TestClass. Quand cette instance est allouée : quand la fonction principale est chargée, ou quand l'affectation de référence est exécutée ? Quand elle est détruite ?

Après la deuxième affectation de référence, l'adresse de l'objet n'est pas modifiée. Cela signifie-t-il que le destructeur et le constructeur sont appliqués à la même zone de mémoire ? Ou bien la mémoire est désallouée (dynamiquement ? sur la pile ?) et réallouée ?

Je sais tout sur la durée de vie des objets alloués à la pile et au tas, leurs constructeurs et leurs destructeurs. Mais je n'arrive pas à comprendre ce qui se passe exactement dans ce programme.

Edit : Merci à tous. J'ai essayé de reproduire dans ce test le comportement d'un autre programme (plus compliqué). Vos commentaires m'ont aidé à comprendre à la fois mon erreur et un autre programme avec lequel je me bats...

Le code fixe est :

int main()
{
    cout << "main started" << endl;
    TestClass t;

    TestClass& c(t);
    c.Dump();

    c = TestClass(10);
    c.Dump();

    cout << "main ended" << endl;
    return 0;
}

5voto

Kerrek SB Points 194696

Votre code souffre de multiples problèmes et n'aura finalement aucun sens. Cependant, essayons de l'améliorer.

1) Vous pouvez seulement lier un temporaire à un const de référence, ce qui prolonge sa durée de vie :

const TestClass & c = TestClass();

2) Maintenant, nous ne pouvons pas utiliser dump parce que vous ne l'avez pas déclaré const :

void Dump() const

3) Disant c = TestClass() est une affectation. Cependant, c est maintenant une référence-à-const, qui ne peut pas être assignée, puisque l'assignation est non-constante (pour des raisons évidentes). Contournons ce problème :

const_cast<TestClass&>(c) = TestClass(10);

Maintenant nous avons assigné une nouvelle valeur à l'objet temporaire-mais-étendu c et tout est comme il se doit :

main started
data = 0  ptr = 0x0xbfa8219c
destructor
data = 10  ptr = 0x0xbfa8219c
main ended
destructor

Les pointeurs sont les mêmes car il n'y a qu'un seul objet, à savoir celui (temporaire) référencé par c . L'assigner est un hack qui est un comportement non défini en général, mais nous nous en sortons pour les besoins de cette démonstration.

Le destructeur intermédiaire est celui du deuxième temporaire TestClass(10) .

2voto

Mahesh Points 20994
TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression.
c.Dump();

TestClass() crée un temporaire et vous ne pouvez pas en prendre la référence.

const TestClass& c = TestClass();

const La qualification prolonge la durée de vie du temporaire en cours de création jusqu'à ce que la portée de l'objet c .

2voto

Nawaz Points 148870
TestClass& c = TestClass();

Ça ne compilerait même pas !

La tentative de lier une référence temporaire à une référence non constante entraînerait une erreur de compilation.

Cependant, vous pouvez lier une référence temporaire à une référence constante :

{
   const TestClass& c = TestClass();
   //use c 
   //....
}//<-------- the temporary will be destroyed here.

Dans ce cas, la durée de vie du temporaire s'étend à la durée de vie de la référence, c'est-à-dire que lorsque la variable de référence sort de sa portée, le temporaire sera détruit comme indiqué ci-dessus.

2voto

Alek86 Points 492

1) vous ne pouvez pas obtenir une référence non constante à un objet temporaire

2) dans la ligne c = TestClass(10) ; operator=(...) est appelé

1voto

Guy L Points 614

Un bon moyen est de comparer les références aux pointeurs... (les références sont généralement implémentées de la même manière en assembleur, en utilisant le registre ebx). La principale différence est que la référence est constante après l'initialisation...

Cependant, la ligne const TestClass& c = TestClass(); est parallèle à const TestClass* const pc = &TestClass(); ainsi l'objet sera créé et détruit sur la pile, pc gardera toujours la même adresse.

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