Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How C++ reference works

Tags:

c++

reference

After working 15 years in C++ I found that I don't understand references completely.

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

I understand from this test that TestClass instance is created on the stack (is this correct?) and initialized by first TestClass constructor. When is this instance allocated: when the main function is loaded or when the reference assignment is executed? When it is destroyed?

After the second reference assignment, the object address is not changed. Does this mean that the destructor and constructor are applied to the same memory area? Or is the memory deallocated (dynamically? on the stack?) and allocated again?

I know everything about stack and heap-allocated objects lifetime, their constructors and destructors, but I cannot understand what exactly happens in this program.

Edit: Thanks to all. I tried to reproduce in this test some other (more complicated) program behavior. Your comments helped me to understand both my mistake and another program I am fighting with...

Fixed code is:

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

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

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

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

Note from 29.06.2022: After latest edition by Daniel Walker this question looks like complete crap. I am not responsible for this.

like image 811
Alex F Avatar asked Feb 12 '26 08:02

Alex F


1 Answers

Your code suffers from multiple problems and ultimately won't make sense. However, let's hack through it.

1) You can only bind a temporary to a const reference, thus extending its lifetime:

const TestClass & c = TestClass();

2) Now we can't use dump, because you didn't declare it const:

void Dump() const

3) Saying c = TestClass() is an assignment. However, c is now a reference-to-const, which cannot be assigned to, since assignment is non-constant (for obvious reasons). Let's hack around this:

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

Now we've assigned a new value to the temporary-but-extended object c, and all is as it should be:

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

The pointers are the same because there's only one object, namely the (temporary) one referenced by c. Assigning to it is a hack that's undefined behaviour in general, but we get away with it for the purpose of this demonstration.

The intermediate destructor is that of the second temporary TestClass(10).

like image 56
Kerrek SB Avatar answered Feb 14 '26 23:02

Kerrek SB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!