Do uninitialized objects exist in C++?
Asked Answered
H

3

22

If all objects have at least one constructor be it default c'tor defined by the compiler or user defined then how can objects be uninitialized.

Hodgson answered 26/9, 2017 at 13:19 Comment(26)
Not all objects have a constructor, like int for instance.Syllepsis
C++ has this funny concept of "default initialized means no initilization is performed" for some cases, such as automatic storage int n;. So it is initialized but it isn't initialized.Ambrosial
By objects i mean class(or union or struct) instancesHodgson
You can put an int inside a class and it will stay uninitialized unless you initialize it.Decorate
Object* obj; would be uninitialized until you also do obj = new Object();Andel
@rimiro Then you should state that in the question. In C++, instances of built-ins are also objects.Ambrosial
Object with user-defined constructor can be still not initialized when used before the constructor is called: foo f = f;Baudelaire
IMO it's easier to consider all object types as having c'tors. It's just that for some those c'tors are no-ops. Hence the indeterminate values.Lynea
@TreytenCarey Object* obj; would be initialized (to nullptr) if it is declared in the global scope.Ambrosial
@TreytenCarey Not initialized implies the pointer already exists. You wouldn't claim some variable meaningOfLife isn't initialized, it doesn't exist in your programMarsiella
@Decorate isnt the int default initialized by the default c'tor a of the object class. So, what is the object said to be initialized or unintialized??Hodgson
@rimiro The wording is somewhat confusing in the standard. When you write int i;, i is default-initialized. But the definition of default-initialization for an int is "no initialization is performed". In colloquial terms, we just call it not initialized.Marsiella
Default constructors of classes just call the default constructors of the members. The default constructor of int doesn't initialize it, so it stays uninitializes.Decorate
@Decorate NathanOliver states that integer dont have c'tor and you are talking about default c'tor of the integer i am confused.Hodgson
You can dig through the standard and find out who is right. It doesn't make a difference here if the default constructor doesn't do anything or doesn't exist.Decorate
@Brandon [intro.object] An object is a region of storage. which means in C++ everything is an object.Syllepsis
@NathanOliver; int is a primitive type.. How can it possibly be an object? An object is structured afaik. I don't know why the standard says that. It's clearly wrong.Lunneta
@Lunneta - It may not be an "Object" according to some definition you pulled off the internet and consider binding. But it is an object as specified by the C++ standard. It's a technical term with important semantics to C++ programmers.Lynea
@Lunneta It's a question of definition. You can define what objects are in your language any way you want. That said there are exceptions. Functions, references and bitfields are not objects if I remember right. Basically anything you can expect memcpy to work on are objects.Decorate
@Lunneta C++ isn't defined as a Object Oriented Language. It has OOP support but it is multi-paradigm. Thus they define everything as an object, whether it is a "primitive" or not.Syllepsis
@Decorate There is an exception for functions, even if they do occupy storage, but it looks like bit fields count. Not sure about references.Syllepsis
@NathanOliver; That's just weird.. int is inherited from C and it isn't defined as Object-Oriented.. Type of int should be the exact same across both languages. We're making excuses for bad definitions and wording imo.. but I guess I can't argue the standard. It just doesn't fit any definition of Object that I know of.Lunneta
@Lunneta - Simple, we don't try to make C++ something that it isn't. Mainly not a language like Java or C#.Lynea
@Lunneta Even C calls everything an object. From Terms, definitions, and symbols: object: region of data storage in the execution environment, the contents of which can represent valuesSyllepsis
@Lunneta - "It should be the same across both languages" - Funny you should say that. Because the C standard also defined object as region of data storage in the execution environment, the contents of which can represent values.Lynea
Folks, if you want to get/give answers about the definition of "object" in C or C++, post a new question about it. The discussion here has gone on long enough...Apache
L
17

It is possible to declare objects on which no initializations are performed. These objects do exist, they have an indeterminate value, and using this value is undefined behavior (there is an exception to this rule for chars).

Such object can be created by default-intialization. This is stated in the c++ standard, (§11.6 Initializers)[dlc.init]:

To default-initialize an object of type T means:

(7.1) — If T is a (possibly cv-qualified) class type (Clause 12), constructors are considered. The applicable constructors are enumerated (16.3.1.3), and the best one for the initializer () is chosen through overload resolution (16.3). The constructor thus selected is called, with an empty argument list, to initialize the object.

(7.2) — If T is an array type, each element is default-initialized.

(7.3) — Otherwise, no initialization is performed.

Nevertheless, static objects are always zero-initialized. So any built-in with dynamic or automatic storage duration may not be initialized, even if it is a suboject;

int i; //zero-initialized

struct A{
  int i;
  };

struct B
  {
  B(){};
   B(int i)
    :i{i}{}
  int i;
  int j;
  };
A a; //a.i is zero-initialized

int main()
  {
   int j;             //not initialized
   int k{};           //zero-initialized
   A b;               //b.i not initialized
   int* p = new int;  //*p not initialized
   A*   q = new A;    //q->i not initialized
   B ab;              //ab.i and ab.j not initialized
   B ab2{1};          //ab.j not initialized
   int xx[10];        //xx's element not initialized.

   int l = i;    //OK l==0;
   int m = j;    //undefined behavior (because j is not initialized)
   int n = b.i;  //undefined behavior 
   int o = *p; //undefined behavior 
   int w = q->i; //undefined behavior 
   int ex = x[0] //undefined behavior
   }

For member initialization [class.base.init] may help:

In a non-delegating constructor, if a given potentially constructed subobject is not designated by a mem- initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then — if the entity is a non-static data member that has a default member initializer (12.2) and either

(9.1.1) — the constructor’s class is a union (12.3), and no other variant member of that union is designated by a mem-initializer-id or

(9.1.2) — the constructor’s class is not a union, and, if the entity is a member of an anonymous union, no other member of that union is designated by a mem-initializer-id, the entity is initialized from its default member initializer as specified in 11.6;

(9.2) — otherwise, if the entity is an anonymous union or a variant member (12.3.1), no initialization is performed;

(9.3) — otherwise, the entity is default-initialized (11.6)

Members of a trivial anonymous union may also not be initialized.


Also one could ask if an object life-time could begin without any initialization, for exemple by using a reinterpret_cast. The answer is no: reinterpret_cast creating a trivially default-constructible object

Lange answered 26/9, 2017 at 15:39 Comment(7)
So int x; is not initialized but int x[10]; is zero-initialized? That doesn't seem right, is there another clause you left out?Rationale
If my memory those not lie to me, these one are documented in the Stroustrup's books! I am for your case.Lange
@MarkRansom Nothing special for array, no initialization is performed. You can check the assembly here: godbolt.org/g/7TJWXgLange
Sorry, I didn't realize that 7.2 is a recursive definition. Either that or I seriously misread it.Rationale
What, no placement new? ::new( (void*)&a ) A; and a.i is no longer initialized.Cesta
@Yakk It has never been initialized!! Look at the assembly in the exemples in c++98 here: no zero initialization. Bonus: value-initialization of class with user declared default constructor dissables zero initialization. So if you do not use the {} initialization form and use classes that partialy initialize non static members, it is better to check twice your code, with the standard under your pillow!Lange
@Yakk Maybe you could have the idea to use a zero-initialized buffer and build a default initialized object of type A on it. This may be equivalent to a zero-initialized object on all major implementation (TBC), but this is not standardized, according to the standard your object has an indeterminate value as if it were built on a not initialized buffer and evaluating its member will lead to UB.Lange
M
2

The standard doesn't talk about existence of objects, however, there is a concept of lifetimes of objects.

Specifically, from [basic.life]

The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and

  • if the object has non-vacuous initialization, its initialization is complete

With non-vacuous initialization defined as

An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its subobjects is initialized by a constructor other than a trivial default constructor.

We can conclude that for objects with vacuous initializations (such as ints), their lifetimes begins as soon as their storage is acquired, even if they are left uninitialized.

void foo()
{
    int i;  // i's lifetime begins after this line, but i is uninitialized
    // ...
}

† Links are added for ease of reading, they don't appear in the standard

Marsiella answered 26/9, 2017 at 13:52 Comment(2)
int i is default initialized as far as i have known and the default c'tor for int does not initialize it (or i is initialized to indeterminate value). Had there been no default c'tor it would be called uninitialized (no doubt on that) but if the default c'tor is present then it can initialize the object in any way it want, even its choice to uninitialize the object may be regarded as some form of its initilization so why should it be considered uninitialized?? //i am just a beginner feel to correct me if i am wrong anywhereHodgson
@rimiro 'uninitialized' refers to the state of the object, not to weather a constructor has been run or not. So if the default c'tor does nothing, the object remains uninitialized and its value indeterminate.Smashing
J
-1

Use byte array:

alignas(alignof(Mat4)) uint8_t result[sizeof(Mat4)];
// ..
node->updateMatrix( ..., /*result*/ reinterprect_cast<Mat4*>(&result[0])); 

The constructors of Mat4 will not trigger.

Jeanniejeannine answered 11/8, 2022 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.