Is this code snippet undefined behavior?

D

davidg

class A
{
public:
A(int x);
...
Amethod();
};

class B
{
public:
B() : a_ref(a), a(42) { }
...
Bmethod() { a_ref.Amethod(); }
...
private:
A &a_ref;
A a;
};

Since the standard states that initializers are executed in the order given in the class definition, this means a_ref is initialized before a, and yet a_ref is trying to reference a.

The reason I ask is that I found the same pattern in the source to the latest Mongodb C++ drivers, and when compiled with GCC it will sometimes wind up leaving a_ref referencing a NULL pointer.

What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I single step from B::Bmethod() into A::Amethod() and inspect "this", it's NULL.
 
V

Victor Bazarov

class A
{
public:
A(int x);
...
Amethod();
};

class B
{
public:
B() : a_ref(a), a(42) { }
...
Bmethod() { a_ref.Amethod(); }
...
private:
A &a_ref;
A a;
};

Since the standard states that initializers are executed in the
order given in the class definition, this means a_ref is initialized
before a, and yet a_ref is trying to reference a.

Not sure what you mean by "yet a_ref is trying to reference a". The
initialization of a reference does not need the value, it does not touch
the value. Essentially it makes sure that when you use 'a_ref'
variable, it will be *as if* you actually used 'a', that's all
*references* are for.

The *object* designated by the 'a' member is not initialized until after
a reference to it is obtained. Undefined behavior? Not sure. I think
it's implementation-defined, but doesn't have to be documented.
The reason I ask is that I found the same pattern in the source to
the latest Mongodb C++ drivers, and when compiled with GCC it will
sometimes wind up leaving a_ref referencing a NULL pointer.

You seem to be saying that GCC implements references as pointers, gives
them storage, and in this particular case using 'a_ref' is like
dereferencing a null pointer because it's initialized with an object
What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I
single step from B::Bmethod() into A::Amethod() and inspect "this",
it's NULL.

That's a QoI issue, I believe. And my opinion of GCC's QoI is not very
high.

Some other compiler *may* do it differently. Although the 'a' object
has not been initialized, the *storage* for it has already been
allocated, and, if your references are pointers behind the scenes, you
can figure out the address of 'a' and initialize 'a_ref' with it even
though the storage itself hasn't been properly run through a constructor
yet. QoI.

V
 
J

Juha Nieminen

Since the standard states that initializers are executed in the
order given in the class definition, this means a_ref is initialized
before a, and yet a_ref is trying to reference a.

Dereferencing an uninitialized object is UB. I don't see any reason why
referencing one would be.
 
G

Gil

class A
{
public:
    A(int x);
    ...
    Amethod();

};

class B
{
public:
    B() : a_ref(a), a(42) { }
    ...
    Bmethod() { a_ref.Amethod(); }
    ...
private:
    A &a_ref;
    A a;

};

Since the standard states that initializers are executed in the order given in the class definition, this means a_ref is initialized before a, and yet a_ref is trying to reference a.

The reason I ask is that I found the same pattern in the source to the latest Mongodb C++ drivers, and when compiled with GCC it will sometimes windup leaving a_ref referencing a NULL pointer.

What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I singlestep from B::Bmethod() into A::Amethod() and inspect "this", it's NULL.

it is well formed in your example as per [basic.life]; note that if
for example you'd try
something like

B() : a_ref( a.i_ ), a(42) { }

where a_ref would be a int reference and class A still non pod - this
time it would be UB.
read [basic.life]/6 and [class.cdtor]/1,2

hth,
gil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top