2

How are fundamental types, such as integers, initialized? Do you they have both move and copy semantics and do they actually have constructors? I got confused when encountered the following about direct initialization:

Otherwise, standard conversions are used, if necessary, to convert the value of other to the cv-unqualified version of T, and the initial value of the object being initialized is the (possibly converted) value.

It is only said that the initial value of the object being initialized is the value, but not how this is done. Is some constructor called, is some memory moved or what will happen?

Is there a detailed explanation of how exactly initialization of fundamental types is done depending on the context? I cannot find it in the standard.

  • 1
    Primitive types such as `int` are *not* classes and instances of them are *not* objects. As such they have no member functions. And as for initialization, it really depends on when and *where* and *how* such variables are defined. – Some programmer dude Jan 12 '18 at 16:32
  • 2
    @Someprogrammerdude Just a clarification: In C++ terminology, _object_ and _instance_ are practically synonyms. Instances of `int` are not "object-oriented objects". – Daniel Langr Jan 12 '18 at 17:24

3 Answers3

2

Primitive types are always copied as there's nothing to move, despite the fact that they can be used in move semantics. Move semantics is originally meant for containers to avoid unnecessary data copying when the source object will be destroyed when the data transition is done. Primitive types aren't containers, you practically cannot "transfer data ownership and leave the original container empty", so there's nothing to move. If you inspect the assembly code generated by any compiler, you'll see the "move" is actually a mov instruction, which means data is simply copied from one register to another, or between memory and registry. This behavior is mostly the same across most modern CPUs due to the architecture.

They do not have constructors or destructors because they are not instances of classes, though they behave as if they have dummy ones.

Their initial state, when first defined without being initialized, be it explicitly or implicitly1, is "indeterminate". You don't know what their value is, or whether it's a trap representation. You can't even do anything with the indeterminate value, including assuming that x == x is true, which is not necessary. So at last, an uninitialized variable of a primitive type is useless (except for unsigned char or any unsigned 1-byte integer equivalent type).

1. A veri simple implicit initialization is when you define a variable at file scope, where it will automatically be zero-initialized. Or when you define a static variable that has the same effect.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • C++ doesn't have the concept of trap representations. With a few rare exceptions, C++ simply doesn't allow reading indeterminate values, even if the type doesn't have what C would call trap representations. –  Jan 12 '18 at 16:38
  • @Someprogrammerdude `static` initialization is covered in my answer by the word "implicit". – iBug Jan 12 '18 at 16:40
  • @FrançoisAndrieux I think you're confused. "Intederminate" means it does have a value, though never predictable or known anyway. – iBug Jan 12 '18 at 16:42
  • 1
    @iBug But it doesn't necessarily have a single value. If `int x;` is uninitialized, you can't assume `x == x`. – François Andrieux Jan 12 '18 at 16:43
  • 1
    @FrançoisAndrieux The term "indeterminate" is actually part of the C++ specification. It says that "if no initialization is performed, an object with automatic or dynamic storage duration has ***indeterminate*** value" (emphasis mine). It simply means that the value can't be *determined*. – Some programmer dude Jan 12 '18 at 16:43
  • @Someprogrammerdude Alright. I guess it's just me then. Thanks. – François Andrieux Jan 12 '18 at 16:44
  • @iBug https://stackoverflow.com/questions/3949471/int-a-a-a-fails Edit : I should clarify, I meant to refer to [this answer](https://stackoverflow.com/a/3949489/7359094) in particular. – François Andrieux Jan 12 '18 at 16:46
  • @FrançoisAndrieux OK, this time I'm wrong. I stand corrected. Thanks. – iBug Jan 12 '18 at 16:49
  • The last paragraph is, I’m pretty sure, true *except for `char`s*. For an `std::byte` or `unsigned char`, you’re allowed to do slightly more (but still not very much). – Daniel H Jan 12 '18 at 17:01
  • @DanielH I am aware of that, but it's only for `unsigned char`, not for `char` or `signed char`. – iBug Jan 12 '18 at 17:02
  • @iBug Yeah, I didn’t fully edit my comment when I double-checked. It’s only `std::byte` and `unsigned char`; I don’t know why they added `std::byte` to the list when they don’t have `signed char` and `char`, but they did. – Daniel H Jan 12 '18 at 17:07
  • It is actually context dependent whether "primitive types" are initially initialised or uninitialised. For example, an `int` at file scope is actually zero-initialised (there is no requirement they ever be uninitialised and then initialised). An `int` of automatic storage duration is uninitialised., so accessing its value gives undefined behaviour. – Peter Jan 12 '18 at 21:27
  • "Fundamental types are always copied as there's nothing to move" - can you elaborate a little, I do not really see why? Thanks again! –  Jan 12 '18 at 22:13
  • @Peter It is covered in my answer with the word "implicit". – iBug Jan 13 '18 at 01:00
  • @iBug Thanks again, but in order to set the initial value, is there some buffer in the fundamental type that holds the value? –  Jan 13 '18 at 09:20
  • Or how is the initial value actually set, like technically? –  Jan 13 '18 at 09:20
  • @iBug I am not thinking about default-initialization. I am thinking about cases such as direct and copy initialization in which the initializer expression is not empty. In these cases, how are the initial value set technically? –  Jan 13 '18 at 10:20
  • @Noe In those cases, the value is simply copied. If you inspect the assembly code, you'll find it's `mov a, b`. Primitive values are often stored directly in memory and registers, so it's simply copied between memory and registers. – iBug Jan 13 '18 at 10:22
  • And they could not be moved, right? Or did I not get that right? –  Jan 13 '18 at 10:23
  • And would you confirm that the process it implementation-specific? and thus the assembly code is not always the same/the steps´? –  Jan 13 '18 at 10:24
  • Alright. Thank you so very much!! I will mark your answer as the solution in a moment :) –  Jan 13 '18 at 10:27
  • @Noe Let's cleanup the comments here. I'll merge the information into my answer. – iBug Jan 13 '18 at 10:29
0

There is no real constructors for fundamental types, but they do behave (mostly) as if they had one. They can also can be moved from, at least semantically - behaving as-if move constructors were defined for them. The move, of course, does not alter the value of the moved-from object.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • So is it defined anywhere how this initialization actually takes place? And how can there only be moved semantics? I mean, it is not always that you wish to move data instead of copying, like when having an lvalue as the initializer. –  Jan 12 '18 at 16:35
  • How much detail of the 'how' are you expecting? As long as it complies with the spec, a compiler is free to do the actual implementation however it likes, so the actual 'how' may be compiler-dependent. – Sean Burton Jan 12 '18 at 16:49
  • @SeanBurton so you are saying that the way fundamental types are instantiated is implementation-specific? If so, are you sure? –  Jan 12 '18 at 18:42
0

For the case you quoted, the standard does not specify how to initialize the object. Because of the as-if rule, an implementation is free to do anything as long as finally the only side effect is that the initial value of the object being initialized becomes the (possibly converted) value of the initializer.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • You are focusing on non-class types, right? For example, doesn't the standard specify how class types are initialized.. –  Jan 13 '18 at 10:20
  • @Noe Yes. I'm just focusing on the case you quoted. – xskxzr Jan 13 '18 at 10:33
  • @Noe So what about upvoting and [accepting](https://meta.stackexchange.com/q/5234/179419) my answer :-) – xskxzr Jan 13 '18 at 11:13