tags:

views:

118

answers:

3

The first print shows the member value to be false, and the other two prints show it as true. Why does the first output differ from the last two?

#include <vector>
#include <iostream>

using namespace std;

class MyClass
{
public:
  bool value;
  bool stuff;
};

class Container
{
public:
  vector<MyClass> my_classes;
  Container()
  {
    MyClass c;
    cout << c.value << endl;
    my_classes.push_back(c);
  }
};

int main (int argc , char* argv[] )
{
  MyClass mc;
  cout << mc.value << endl;
  Container con;
  cout << con.my_classes[0].value << endl;
  return 0;
}
+7  A: 

The two members are primitive (non-class) objects and thus uninitialized. That means that their values will be arbitrary at runtime. You must initialize them in the constructor:

class MyClass {
public:
  bool value;
  bool stuff;
  MyClass(): value(false), stuff(false) { }
};
Philipp
Class vs struct doesn't affect this. The constructor is the significant thing.
Potatoswatter
Why is the first print consistently false (or a particular integer) while the second two prints have the same value, different from the first? Dumb luck? Compiler differences? The output values also seem to differ based on the number of MyClass members.
anachoret
@anachoret: dumb luck.
Potatoswatter
Usually when the OS allocates a page for the first time it filled with zeros. So at first you see false. But once your code keeps on running the memory area of your stack no longer has those zeros and you see different results.Anyhow, it's all a matter of luck mostly.*NEVER LEAVE ANY VARIABLE INITIALIZED*(* Unless you know what you're doing)(** You probably don't :)
Shiroko
This `MyClass(): value(), stuff() { }` would have worked, too. (The default is to initialize `bool` to false.)
sbi
@Shiroko: Did you mean _un_initialized?
sbi
Will there be a a problem when adding a class to a vector? I.E. is class member initialization enough, or must one also define a copy constructor for the class too?
anachoret
@Potatoswatter: Yes, I didn’t mention `struct` at all. But maybe “primitive” is not the correct term for denoting the types that are not default-initialized—C++ parlance generally looks a bit idiosyncratic to me.@Shiroko: uninitialized variables sometimes make sense if performance is top priority: if you can be sure that they are assigned later or not used, you don’t have to initialize them.
Philipp
@anachoret: The compiler synthesizes the copy constructor and assignment operator if they aren't explicitly defined. In your example, the synthesized members are just fine. For more complex classes, you often have to declare or defined these members explicitly; sometimes the “Law of the Big Three” is helpful in that case.
Philipp
@sbi: Oops, forgot two letters. so what? :)
Shiroko
+3  A: 

You are not initializing members to any value. They will just have any value that was in that place of memory before.

Messa
Why does the first construction of MyClass and subsequent print inside of Container always initialize bools to false?
anachoret
it doesn't. it just happens that the piece of memory it's using happens to always contain that value. If you rearrange your program or add to it its likely that it will change
John Burton
+1  A: 

The objects you are declaring in main(..) are automatic hence allocated on the stack of the running thread. Since you don't initialize the objects, they are simply filled with the data that was previously in this very part of the stack.

If you processor is of intel x86 architecture, the assembly language code for a typical function would look something like this (AT&T syntax)

pushl   %ebp 
movl    %esp, %ebp
subl    $LOCAL_VARIABLES_NUM * WORD_SIZE, %esp

...
<function code goes here>
<that is how we read variable values>
movl -4(%ebp), %ebx        
...

addl $LOCAL_VARIABLES_NUM * WORD_SIZE, %esp
popl %ebp

As you see, we simply add and substract the necessary number of bytes from the stack pointer, leaving the old data where it was.

Negai