0

Possible Duplicate:
Can a local variable's memory be accessed outside its scope?
C++ constructor: garbage while initialization of const reference

This question is directly related to another question that I've asked a time ago: "Opaque reference instead of PImpl. Is it possible?".

Let's say we have a class with a reference member of some other class which is initialized to a temporary variable in a constructor:

#include <iostream>

struct B
{
    B(int new_x = 10) : x(new_x) { std::cout << "B constructed\n"; }
    ~B() { std::cout << "B destroyed\n"; }

public:
    int x;
};

struct A
{
    A()
    : b( B(23) )
    {
        std::cout << "A constructed\n";
    }

    void Foo()
    {
        std::cout << "A::Foo()\n";
    }

    ~A()
    {
        std::cout << "A destroyed\n";
    }

public:
    const B& b;
};

int main()
{
    A a;
    a.Foo();
    cout << "x = " << a.b.x << endl;
}

When I run the code above, the output is:

B constructed
B destroyed
A constructed
A::Foo()
x = 23
A destroyed

It seems that even if temporary is destroyed so the reference member should be invalid, the integer field of the reference member is still readable. Why does it still work?

Community
  • 1
  • 1
ezpresso
  • 7,896
  • 13
  • 62
  • 94
  • 7
    It's undefined behaviour. There is no "why". – Kerrek SB Sep 26 '12 at 13:34
  • 1
    The memory still contains the value `23`. See [Can a local variable be accessed outside its scope](http://stackoverflow.com/a/6445794/597607) – Bo Persson Sep 26 '12 at 13:37
  • This outstanding answer by Eric Lippert: [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) answers your question as well. Voted to close as a dupe. – sbi Sep 26 '12 at 13:38
  • 1
    Add a couple of function calls in between and you might get some garbage... – David Rodríguez - dribeas Sep 26 '12 at 14:17

3 Answers3

1

Undefined behaviour. It so happens in your case that the memory previously occupied by the temporary B is not overwritten before you reference it. Next time you run the program, anything could happen.

Note that the superficially similar

const B &b = B();

does have defined behaviour; the lifetime of the temporary B is extended through reference binding. This only applies to reference variables, not reference members.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

If a reference is invalid, that doesn't mean it's unreadable. It means that it doesn't refer to a valid object. It may or may not refer to some piece of accessible memory; if it does, you may or may not find that the memory contains the remnants of whatever object used to be there.

To summarise, the behaviour is undefined.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

The memory that has been allocated to the temporary B is now invalid, but it has not been put to any other use. That is why your read produces the value that was there the last time. However, this is undefined behavior. Running valgrind should pinpoint the place of the error.

If you are wondering "how can it be", here is a great answer explaining what happens in a very similar situation.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523