Reputation: 17945
I would like to know the rule for zeroing-out structs (or classes) that have no default constructor in C++.
In particular, it seems that if stored in the stack (say, as a local variable) they are uninitialized, but if allocated on the heap, they are zero-initialized (tested with GCC 4.9.1). Is this guaranteed to be portable?
Example program:
#include <iostream>
#include <map>
using namespace std;
struct X {
int i, j, k;
void show() { cout << i << " " << j << " " << k << endl; }
};
int fib(int i) {
return (i > 1) ? fib(i-1) + fib(i-2) : 1;
}
int main() {
map<int, X> m;
fib(10); // fills the stack with cruft
X x1; // local
X &x2 = m[1]; // heap-allocated within map
X *x3 = new X(); // explicitly heap-allocated
x1.show(); // --> outputs whatever was on the heap in those positions
x2.show(); // --> outputs 0 0 0
x3->show(); // --> outputs 0 0 0
return 0;
}
Edited: removed an "or should I just use a constructor" in the bolded part; because what made me ask is that I want to know if it is guaranteed behaviour or not - we can all agree that readable code is better of with explicit constructors.
Upvotes: 2
Views: 1035
Reputation: 182
As long as you don't have any constructors, all members are public, and there is no inheritance involved, your struct/class is likely an aggregate.
To get portable zero-initialization, simply use X x = {};
which performs zero intialization.
Here is the standard quote about aggregates (8.5.1):
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
reference: Why can I not brace initialize a struct derived from another struct?
Upvotes: 0
Reputation: 385194
It's not the dynamic allocation that's zero-initialising your struct
members; it's your syntax:
X* ptr = new X();
// ^^
//
// as opposed to just:
X* ptr = new X;
If you want it guaranteed, just keep writing that. :)
An alternative, which meshes well with the automatic-storage-duration equivalent, is to use the newer {}
syntax:
X* ptr = new X{}; // dynamic
X obj{}; // automatic
And objects with static storage duration are always pre-zero-initialised no matter what, so you're covered there by default.
Upvotes: 5
Reputation: 146940
Always use a constructor if you want to give your class's members particular values. That's literally what constructors are for. The only time you don't need to write a constructor that sets the values you want is if the language pre-provides one for you like copy constructor. Default constructor is not on this list for int
and other such types so you have to add a constructor to your own type that sets them appropriately.
Upvotes: 3