11

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?

JBL
  • 12,588
  • 4
  • 53
  • 84
  • 3
    Maybe these questions help https://stackoverflow.com/q/3996855/1741542 and https://stackoverflow.com/q/11338601/1741542 – Olaf Dietsche Feb 22 '18 at 10:45
  • 1
    @OlafDietsche these deal with subobjects of the object being constructed, which has a special case in the standard IIRC. This one is about an unrelated object. – Quentin Feb 22 '18 at 10:48
  • 2
    The object `object2` *exists* (but in an indeterminate unconstructed state) when `object` is constructed. Therefore I'd say that it's valid, as long as you don't do anything with the referenced object until it has been constructed. If you want an authoritative answer I suggest adding the `language-lawyer` tag. – Some programmer dude Feb 22 '18 at 10:56
  • Consider: https://tio.run/##Sy4o0E3OScxL//@/uKSoNLlEwS0/X6GaSwEIQCy1otS0eGs4VwMipqlgpQCS0ACyqmu5aq25uFIrSlKL8sCK0vLzjay5oCwNEE8TzjUC8TWt/2fmlSjkJmbmKWiATPgPAA – jxh Feb 22 '18 at 11:05
  • 1
    It is a classic problem in C++ to reference global objects before they are constructed. So long as you are only referring to their references or pointers, it is fine. In the general case, there is no guarantee on the order of global object construction, because global objects may be in separate translation units. – jxh Feb 22 '18 at 11:09
  • See [Is passing a C++ object into its own constructor legal?](https://stackoverflow.com/a/32608695/1708801) note defect report 363 and active issue 453 – Shafik Yaghmour Mar 08 '18 at 02:36

1 Answers1

15

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.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Thanks. I wonder if (7.1) includes assigning to a (trivially copyable) object? – finnw Oct 19 '19 at 12:28
  • @finnw Hmm, that's an interesting question. I would say it should be OK. "Using the properties of the glvalue that do not depend on its value is well-defined". – n. m. could be an AI Oct 19 '19 at 13:53