views:

2409

answers:

8

In the book I'm reading at the moment (C++ Without Fear) it says that if you don't declare a default constructor for a class, the compiler supplies one for you, which "zeroes out each data member". I've experimented with this, and I'm not seeing any zeroing -out behaviour. I also can't find anything that mentions this on Google. Is this just an error or a quirk of a specific compiler?

+2  A: 

C++ does not guarantee zeroing out memory. Java and C# do (in a manner of speaking).

Some compilers might, but don't depend on that.

Jason Cohen
+7  A: 

C++ does generate a default constructor but only if you don't provide one of your own. The standard says nothing about zeroing out data members. By default when you first construct any object, they're undefined.

This might be confusing because most of the C++ primitive types DO have default "constructors" that init them to zero (int(), bool(), double(), long(), etc.), but the compiler doesn't call them to init POD members like it does for object members.

It's worth noting that the STL does use these constructors to default-construct the contents of containers that hold primitive types. You can take a look at this question for more details on how things in STL containers get inited.

tgamblin
+1  A: 

C++ generates a default constructor. If needed (determined at compile time I believe), it will also generate a default copy constructor and a default assignment constructor. I haven't heard anything about guarantees for zeroing memory though.

Jason Punyon
+5  A: 

The compiler will generate default constructors and destructors if user-created ones are not present. These will NOT modify the state of any data members.

In C++ (and C) the contents of any allocated data is not guaranteed. In debug configurations some platforms will set this to a known value (e.g. 0xFEFEFEFE) to help identify bugs, but this should not be relied upon.

Andrew Grant
The value used in debug mode is compiler dependant. And different values usually represent different states. Like Allocated/Deallocated/Not Initialized etc.
Martin York
To clarify, those tagging values are usually set by the memory management library (operator new(), malloc, and derivatives), not by the compiler creating default constructors.
Euro Micelli
+1  A: 

Zero-ing out only occurs for globals. So if your object is declared in the global scope, its members will be zero-ed out:

class Blah
{
public:
    int x;
    int y;
};

Blah global;

int main(int argc, char **argv) {
    Blah local;
    cout<<global.x<<endl;  // will be 0
    cout<<local.x<<endl;   // will be random
}
codelogic
Compiler dependent.
Johann Gerell
It's part of the standard though. Do you know a complaint compiler that doesn't zero out globals?
codelogic
+5  A: 

The default constructor created for a class will not initialize built-in types, but it will call the default constructor on all user-defined members:

class Foo
{
public:
     int x;
     Foo() : x(1) {}
};

class Bar
{
public:
     int y;
     Foo f;
     Foo *fp;
};

int main()
{

    Bar b1; 
    ASSERT(b1.f.x == 1); 
    // We know nothing about what b1.y is set to, or what b1.fp is set to.

    // The class members' initialization parallels normal stack initialization.
    int y;  
    Foo f; 
    Foo *fp; 
    ASSERT(f.x == 1);
    // We know nothing about what y is set to, or what fp is set to.

}
Eclipse
+12  A: 

If you do not define a constructor the compiler will define a default constructor for you.

The implementation of this

default constructor is:

  • default construct the base class (if the base class does not have a default constructor this is a compilation failure)
  • default construct each member variable in the order of declaration. (If a member does not have a default constructor this is a compilation failure).

Note:
That POD data (int,float,pointer etc) do not have an explicit constructor but the default action is too do nothing (in the vane of C++ philosophy; we do not want to pay for somthing unless we explicitly ask for it).

If no destructor/copy Constructor/Assignment operator is defined the compiler builds one of those for you (so a class always has a destructor/Copy Constructor/Assignment Operator (unless you cheat and explicity declare one but don't define it)).
The default implementation is:

Destructor:

  • If user defined destructor defined execute the code provided.
  • Call the destructor of each member in reverse order of declaration
  • Call the destructor of the base class.

Copy Constructor:

  • Call the Base class Copy Constructor.
  • Call the copy constructor for each member variable in the order of declaration.

Assignment Operator:

  • Call the base class assignment operator
  • Call the assignment operator of each member variable in the order of declaration.
  • Return a reference to this.

Note Copy Construction/Assignemtn operator of POD Data is just copying the data (Hence the shallow copy problem associated with RAW pointers).

Martin York
From section 8.5 item 5 in the standard: _"To default-initialize an object of type T means: ... [if the T is POD] the object is zero-initialized."_ and from item 4 of the same section: _"To zero-initialize an object of type T means: if T is a scalar type, the object is set to the value 0 (zero), taken as an integral constant expression, converted to T"_ . For POD, if I am not mistaken, this means `int i = int();` concludes with `i == 0`
wilhelmtell
@wilhelmtell: That is when you __explicitly__ use the default initialized. In the above situation the POD types are not explicitly default initialized so there values are undefined. This is why I use the slightly more ambiguous term of default constructor.
Martin York
+2  A: 

I think it's worth pointing out that the default constructor will only be created by the compiler if you provide no constructor whatsoever. That means if you only provide one constructor that takes an argument, the compiler will not create the default no-arg constructor for you.

The zeroing-out behavior that your book talks about is probably specific to a particular compiler. I've always assumed that it can vary and that you should explicitly initialize any data members.

Bill the Lizard