Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to uninitialized object

Before explaining the question i want to mark that i know that given example is bad code. I am already looking at std::shared_ptr to achieve my goal in more reasonable way. Reason for this post is just my curiosity and desire to learn new stuff. Thank You in advance for help!

I was today a little messing with my parser code. Optimalization stuff etc. I focused on few instances of object that where unnecesarly cloned all the way throught parsing. I had not-so-deliberate idea to create few global instances and access them by static method. Anyway (strongly simplifing) i ended with this somewhat interesting case:

class class_a
{
    class_a();
    class_a& referenceToObject;
};

class_a& getGlobalObject();

class_a::class_a()
:referenceToObject(getGlobalObject())
{}

class_a object;
class_a object2;

class_a& getGlobalObject()
{
    return object2;
}

This obviously means that i did quite a few things very wrong, but at this branch, optimization is the most important matter.

I am interested what would happen in code like this in wider collection of compilers. GetGlobalObject() is returning reference to object that hadn't it's constructor called. Still it's returning only the reference - that is pointer to space on memory (somewhere on data segment or heap, dunno) known at compile time.

Assuming that nothing will call any method nor any member of object2 reference, is this example undefined behavior?

like image 357
Jakub Jakubowski Avatar asked Feb 22 '18 10:02

Jakub Jakubowski


1 Answers

Yes it is perfectly legal to pass around references to objects that were not constructed yet, and even use such references in certain limited ways.

[basic.life] ... Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. Otherwise, such a glvalue refers to allocated storage ([basic.stc.dynamic.allocation]), and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
(7.1) the glvalue is used to access the object, or
(7.2) the glvalue is used to call a non-static member function of the object, or
(7.3) the glvalue is bound to a reference to a virtual base class ([dcl.init.ref]), or
(7.4) the glvalue is used as the operand of a dynamic_­cast ([expr.dynamic.cast]) or as the operand of typeid.

As long as you are not doing anything of the above, you are in the clear.

like image 154
n. 1.8e9-where's-my-share m. Avatar answered Nov 02 '22 17:11

n. 1.8e9-where's-my-share m.