5

Lets say I have this class:

class X {
public:
    int x;
};

I saw that if I create an instance of X locally, x will not be initialize to 0, only if I create it globally.
Does this mean that the default constructor isn't synthesized by the compiler(I doubt it) for objects created localy or it will be synthesized but not zero out x value, if this is the case why is that ?

Adrian
  • 19,440
  • 34
  • 112
  • 219
  • 1
    `int` never has a default constructor, it's a primitive. The fact that sometimes it's 0 for you is a fluke, and not required by any standard. Always always always initialize your variables. – Chris Eberle May 09 '11 at 20:51
  • 2
    @Chris: it isn't a fluke. Objects with static storage duration (which includes most globals) are zero-initialized before any other initialization occurs. This means global int values start off as 0. – Dennis Zickefoose May 09 '11 at 21:01
  • The reason you are not getting useful or correct answers is because the actual answer would take several pages of a good C++ text book - which one are you reading? –  May 09 '11 at 21:03
  • The answer depends, in part, upon how you "create an instance of X locally". Do you say `X x;`, `X x = X();`, `X*p = new X;`, or `X *p = new X();` ? – Robᵩ May 09 '11 at 21:06
  • @Dennis Zickefoose: interesting. Now I know, and knowing > 0.5 * battle. – Chris Eberle May 09 '11 at 21:07
  • @ unapersson: Im reading from C++ Object Model, if the question was for me :) – Adrian May 09 '11 at 21:08
  • @Rob: doest it matter how you create it ? i get same result even if I create it an the stack or an the heap – Adrian May 09 '11 at 21:10
  • Yes, it matters how you create local variables. `X x;` is different than `X x = X()`. – Robᵩ May 09 '11 at 21:16
  • @Rob: I know its diferent, but i mean that it gives the same result even if I do X x or X* x = new X; – Adrian May 09 '11 at 21:18
  • @vBx Not the greatest book, IMHO. And certainly not one that describes construction in any great detail, if I recall. But it's years since I read it. –  May 09 '11 at 21:24
  • @ unapersson: I saw here on the site good remarks....can you point something better from what you read then ?:) – Adrian May 09 '11 at 21:28
  • @vBx Depends what you want to learn. My personal favourite C++ book for beginners is Accelerated C++. But I've been using and teaching C++ for over 25 years now, so its kind of hard to recommend beginner/intermediate books, as I no longer read them. –  May 09 '11 at 21:33

4 Answers4

4

Constructors in C++ don't generally initialize members to 0. You have to explicitly initialize members with a value.

The reason that in the global case the memory is zero, is because static memory gets initialized to zero before anything else happens to it. In your case, the implicitly generated default constructor gets called afterwards, which does not touch the memory for member X.

See also this answer from Derek: Is global memory initialized in C++?

Note, however, that default constructors for structured, non-POD members (classes and structs) do automatically get called by the default constructor. It's just the POD members that are left alone by default.

Community
  • 1
  • 1
TheFogger
  • 2,399
  • 1
  • 20
  • 22
  • But if create an instance of X globally, it will initialize x to 0 by the default constructor synthesized by the compiler – Adrian May 09 '11 at 20:53
  • 1
    This is also wrong. The reality is more complicated. But importantly, global memory is *not* “zeroed out”, constructors *do* get called on non-PODs. – Konrad Rudolph May 09 '11 at 20:54
  • @Konrad It doesn't? Can you elaborate? – TheFogger May 09 '11 at 20:55
  • @TheFogger As I’ve already said: for non-PODs, the default constructor is called. – Konrad Rudolph May 09 '11 at 20:59
  • @Konrad Rudolph I mean your comment that global memory does not get "zeroed out". I just did a search and found an answer from Derek, which I linked above. It is my impression that global memory does, in fact, get intialized to zero. – TheFogger May 09 '11 at 21:04
  • 1
    @TheFogger I can only repeat myself: for non-PODs, this simply isn’t the case. Global objects of non-PODs do not get zeroed out, their default constructor gets called. See for yourself: https://gist.github.com/963414 – Konrad Rudolph May 09 '11 at 21:06
  • @Konrad Rudolph I admit, I do not have a copy of the standard at hand. How would you interpret this quote from Dereks answer? _Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place._ I was under the impression that a global object, POD or not, does have static storage duration, and thus this sentence applies. – TheFogger May 09 '11 at 21:12
  • 2
    @TheFogger Non-POD statics are zero initialised and then constructors are called on them. –  May 09 '11 at 21:19
  • 1
    I think I see where our misunderstanding is. The memory does get zeroed out, but the default constructor gets called afterwards. If you do not specify a default constructor, the implicitly generated one will not do anything to POD members. Thus, they will stay zero. – TheFogger May 09 '11 at 21:20
  • @Konrad Rudolph - non-PODs are zeroed out prior to any other initialization. Later, their default constructors are invoked. See C++03 8.5, para 6: "Every object of static storage duration shall be zero-initialized at program startup before any other initialization takes place. \[ *Note*: in some cases, additional initialization is done later. \]". Also see, this (non-conclusive) proof: http://ideone.com/iIrU0 – Robᵩ May 09 '11 at 21:23
  • @Rob @TheFogger I see. This makes some sense since the order of initialisation of global objects isn’t trivial. – Konrad Rudolph May 10 '11 at 07:06
  • @Rob a note about your example: the effect observed here is *completely* (!) unrelated: values are initialised in the initialiser list. Since you don’t do that, an implicit initialisation is generated (for each member). In the constructor body, these initialisers have already been executed. To circumvent this you need to output the member’s value *inside* the initialiser list. Unfortunately, this will still always yield 0 on ideone (presumably because of their sandbox). – Konrad Rudolph May 10 '11 at 08:18
  • @Konrad -- no, it will always yield zero (on static-duration non-POD objects) because that is the required behavior. All globals must be zero-initialized before any global's constructor is invoked. – Robᵩ May 10 '11 at 15:12
  • @Rob Only for global variables. But your code will also always yield 0 for local variables because the output happens after the member variable has been initialised (even PODs have initialisers). – Konrad Rudolph May 10 '11 at 15:23
2

X gets a synthesised constructor, but synthesised constructors do not zero-initialise primitives.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

You are combining the concept of object construction with member initialization. As a general rule, don't expect C++ to initialize primitive data members for you, you'll need to do that yourself (preferably via an initialization list after the constructor.)

This is primarily for speed, as this allows allocation without initialization, which is useful if, for instance, you will be computing the values of the data members later and overwriting any "default" values.

I've found this site a useful reference in the past: http://www.cplusplus.com/doc/tutorial/variables/

holtavolt
  • 4,378
  • 1
  • 26
  • 40
-1

Default constructors are not aware that it should initialize your member variables. If you need to initialize x to something, you better add your own constructor to do this for you:

class X {
public:
    X() : x(0) { };
    int x;
};
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • But if my object is create it outside of any function(global) why does it have aware of my member x ? Because it will initilize it to 0 – Adrian May 09 '11 at 20:54
  • 2
    The compiler synthesised default constructor is certainly "aware" of your member variables. Whether it initialises them is another issue. –  May 09 '11 at 20:55
  • I meant that the compiler is not aware that the default constructor should initialize private member variables. I'm not a native English speaker, give this brother a break. **;D** It has been fixed, thanks for pointing it out. Remove the downvote when you can, thanks. – karlphillip May 09 '11 at 21:06
  • This has nothing to do with private member variables. The synthesised constructor certainly will initialise private member variables (via their constructors) if it can. This whole area is much more complex than youseem to think - hence the downvote. –  May 09 '11 at 21:12
  • "It should initialize your member variables" is subjective. The default constructor is not unaware of the scenario; simply, the language chooses not to do it. – Lightness Races in Orbit May 09 '11 at 21:53
  • @vBx: Because when it's global, it's statically allocated and therefore zero-initialised as one of the first steps in your program, according to separate rules of the language. – Lightness Races in Orbit May 09 '11 at 21:54
  • @unapersson Totally agree. The *private* thing was a mistake. Anyway, it was only added on my comment and not on the answer. Thanks. – karlphillip May 09 '11 at 22:39