I have a question about the default initialization in C++. I was told the non-POD object will be initialized automatically. But I am confused by the code below.
Why when I use a pointer, the variable i is initialized to 0, however, when I declare a local variable, it's not. I am using g++ as the compiler.
class INT {
public: int i;
};
int main () {
INT* myint1 = new INT;
INT myint2;
cout<<"myint1.i is "<<myint1->i<<endl;
cout<<"myint2.i is "<<myint2.i<<endl;
return 0;
}
The output is
myint1.i is 0
myint2.i is -1078649848
You need to declare a c'tor in INT and force 'i' to a well-defined value.
class INT {
public:
INT() : i(0) {}
...
};
i is still a POD, and is thus not initialized by default. It doesn't make a difference whether you allocate on the stack or from the heap - in both cases, the value if i is undefined.
in both cases its not initialized, you were just lucky to get 0 in the first one
It depends on the compiler. The big difference here is that a pointer set to new Something refers to some area of memory in heap, while local variables are stored on the stack. Perhaps your compiler zeroes heap memory but doesn't bother zeroing stack memory; either way, you can't count on either method zeroing your memory. You should use something like ZeroMemory in Win32 or memset from the C standard libraries to zero your memory, or set i = 0 in the constructor of INT.
For a class or struct-type, if you don't tell it which constructor to use when defining a variable, then the default constructor is called. If you didn't define a default constructor, then the compiler creates one for you. If the type is not a class (or struct) type, then it is not initialized since it won't have a constructor, let alone a default constructor (so no built-in types like int will ever be default-initialized).
So, in your example, both myint1 and myint2 are default constructed with the default constuctor that the compiler declared for INT. But since that won't initialize any non-class/struct variables in an INT, the i member variable of INT is not initialized.
If you want i to be initialized, you need to write a default constructor for INT which initializes it.
Firstly, your class INT is POD.
Secondly, when something is "initialized automatically" (for automatic or dynamic objects), it means that the constructor is called automatically. There is no other "automatic" initialization scenario (for automatic or dynamic objects); all other scenarios require a "manually" specified initializer. However, if the constructor does not do anything to perform the desired initialization, then that initialization will not take place. It is your responsibility to write that constructor, when necessary.
In both cases in your example you should get garbage in your objects. The 0 that you observe in case of new-ed object is there purely by accident.
That's true for non-POD object's but your object is POD since it has no user defined constructor and only contains PODs itself.
We just had this topic, you can find some explinations here.
If you add more variables to the class, you will end up with non-initialized member variables.
Related
I know that if a C++ struct is Plain Old Data ("POD") then this guarantees there is no magic in its memory structure, so it means a memcpy to an array of bytes and memcpy back is safe.
I also know that in the standard a POD struct should not have user-defined constructor. In the project I own now, there are some plain structs (with only data fields) with a default constructor defined which initializies the data members to 0. I saw other clients would use memset(&obj, 0, sizeof obj); before using the struct.
Is it ok or safe to memset the non-POD struct before I use it?
Having a constructor does not make a struct non-POD.
An aggregate class is called a POD if it has no user-defined copy-assignment operator and destructor and none of its nonstatic members is a non-POD class, array of non-POD, or a reference.
Given that, it is perfectly safe to call
memset(&obj, 0, sizeof obj);
on an object of a struct that has a constructor as long as it is a POD.
Whether it is OK or not, depends. If the default constructor of the struct wants a member to be initialized to 1 for sane behavior, the above call to memset may impact the behavior of code that depends on 1 being the default value.
Take the example of the following struct:
struct Direction
{
Direction() : x(1.0), y(0.0), z(0.0) {}
double x;
double y;
double z;
};
An object of type Direction expects that at least of one of the components will be non-zero. You can't define a direction when all the components are zero. If you use memset to set everything to 0, code will likely break.
EDIT
It appears, from the comments below, as though the definition of a POD has changed from C++03 to C++11.
Using memset(&obj, 0, sizeof obj); may not be safe after all.
IMO this depends on the use case. I have seen memset used to set the data with white space character on few mainframe appications i.e
memset(&obj, ' ', sizeof(obj));
In case the struct defines a const variable and initializes the value, memset would override such value. So it depends and most cases safe to use memset to initialize for PODS. thats my 2 cents.
I'm curious if these are zero initialized and all my pointers are 0 when I declare a fixed size array. I can say foo* arr[1000][1000] and I see that all the entries are 0..but I am not sure if this is something I can rely on or not. I could say foo* arr[1000][1000] = {} but this double array is a member variable in a class and I wouldn't want to have a double for loop in the constructor if it's not necessary...
Depends on how you allocate the array.
If it's static or global, then the contents will all be initialised to 0. If it's a local variable, then the contents won't be initialised to anything.
So since your array is a member variable, it won't be initialised to 0 automatically. However, you can initialise all the variables to zero by using the initialisation list in the constructor thusly:
struct A {
// VVV value-initialises the contents of arr
A() : arr() { }
double arr[x][y];
};
It depends on the context. If the array is defined at namespace level, then static initialization will set all pointers to null for you. If it is defined in a function scope or as a member of a class, there is no such guarantee.
Since it is a member of a class, it will not be correctly initialized, so you will need to initialize it manually. You can do so by adding arr() to the initialization list. Being pointers, you can use memset to set the whole array to 0 in a single call (which will also be as efficient as it gets), but beware, this only works for POD types.
Note: I am using the g++ compiler (which is I hear is pretty good and supposed to be pretty close to the standard).
I have the simplest class I could think of:
class BaseClass {
public:
int pub;
};
Then I have three equally simple programs to create BaseClass object(s) and print out the [uninitialized] value of their data.
Case 1
BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
This prints out:
B1.pub = 1629556548
Which is fine. I actually thought it would get initialized to zero because it is a POD or Plain Old Datatype or something like that, but I guess not? So far so good.
Case 2
BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
This prints out:
B1.pub = 1629556548
B2.pub = 0
This is definitely weird. I created two of the same objects the same exact way. One got initialized and the other did not.
Case 3
BaseClass B1;
cout<<"B1.pub = "<<B1.pub<<endl;
BaseClass B2;
cout<<"B2.pub = "<<B2.pub<<endl;
BaseClass* pB3 = new BaseClass;
cout<<"B3.pub = "<<pB3->pub<<endl;
This prints out:
B1.pub = 0
B2.pub = 0
B3.pub = 0
This is the most weird yet. They all get initialized to zero. All I did was add two lines of code and it changed the previous behavior.
So is this just a case of 'uninitialized data leads to unspecified behavior' or is there something more logical going on 'under the hood'?
I really want to understand the default constructor/destructor behavior because I have a feeling that it will be very important for completely understanding the inheritance stuff..
So is this just a case of 'uninitialized data leads to unspecified behavior'
Yes...
Sometimes if you call malloc (or new, which calls malloc) you will get data that is filled with zeroes because it is in a fresh page from the kernel. Other times it will be full of junk. If you put something on the stack (i.e., auto storage), you will almost certainly get garbage — but it can be hard to debug, because on your system that garbage might happen to be somewhat predictable. And with objects on the stack, you'll find that changing code in a completely different source file can change the values you see in an uninitialized data structure.
About POD: Whether or not something is POD is really a red herring here. I only explained it because the question mentioned POD, and the conversation derailed from there. The two relevant concepts are storage duration and constructors. POD objects don't have constructors, but not everything without a constructor is POD. (Technically, POD objects don't have non-trivial constructors nor members with non-trivial constructors.)
Storage duration: There are three kinds. Static duration is for globals, automatic is for local variables, and dynamic is for objects on the heap. (This is a simplification and not exactly correct, but you can read the C++ standard yourself if you need something exactly correct.)
Anything with static storage duration gets initialized to zero. So if you make a global instance of BaseClass, then its pub member will be zero (at first). Since you put it on the stack and the heap, this rule does not apply — and you don't do anything else to initialize it, so it is uninitialized. It happens to contain whatever junk was left in memory by the last piece of code to use it.
As a rule, any POD on the heap or the stack will be uninitialized unless you initialize it yourself, and the value will be undefined, possible changing when you recompile or run the program again. As a rule, any global POD will get initialized to zero unless you initialize it to something else.
Detecting uninitialized values: Try using Valgrind's memcheck tool, it will help you find where you use uninitialized values — these are usually errors.
It depends how you declare them:
// Assuming the POD type's
class BaseClass
{
public:
int pub;
};
Static Storage Duration Objects
These objects are always zero initialized.
// Static storage duration objects:
// PODS are zero initialized.
BaseClass global; // Zero initialized pub = 0
void plop()
{
static BaseClass functionStatic; // Zero initialized.
}
Automatic/Dynamic Storage Duration Objects
These objects may by default or zero initialized depending on how you declare them
void plop1()
{
// Dynamic
BaseClass* dynaObj1 = new BaseClass; // Default initialized (does nothing)
BaseClass* dynaObj2 = new BaseClass(); // Zero Initialized
// Automatic
BaseClass autoObj1; // Default initialized (does nothing)
BaseClass autoObj2 = BaseClass(); // Zero Initialized
// Notice that zero initialization of an automatic object is not the same
// as the zero initialization of a dynamic object this is because of the most
// vexing parse problem
BaseClass autoObj3(); // Unfortunately not a zero initialized object.
// Its a forward declaration of a function.
}
I use the term 'Zero-Initialized'/'Default-Initialization' but technically slightly more complex. 'Default-Initialization' will becomes 'no-initialization' of the pub member. While the () invokes 'Value-Initialization' that becomes 'Zero-Initialization' of the pub member.
Note: As BaseClass is a POD this class behaves just like the builtin types. If you swap BaseClass for any of the standard type the behavior is the same.
In all three cases, those POD objects could have indeterminate values.
POD objects without any initializer will NOT be initialized by default value. They just contain garbage..
From Standard 8.5 Initializers,
"If no initializer is specified for an object, and the object is of
(possibly cv-qualified) non-POD class type (or array thereof), the
object shall be default-initialized; if the object is of
const-qualified type, the underlying class type shall have a
user-declared default constructor. Otherwise, if no initializer is
specified for a nonstatic object, the object and its subobjects, if
any, have an indeterminate initial value; if the object or any of
its subobjects are of const-qualified type, the program is
ill-formed."
You can zero initialize all the members of a POD struct like this,
BaseClass object={0};
The way you wrote your class, the value of pub is undefined and can be anything. If you create a default constructor that will call the default constructor of pub - it will be guaranteed to be zero:
class BaseClass {
public:
BaseClass() : pub() {}; // calling pub() guarantees it to be zero.
int pub;
};
That would be a much better practice.
As a general rule, yes, uninitialized data leads to unspecified behavior. That's why other languages like C# take steps to insure that you don't use uninitialized data.
This is why you always, always, always, initialize a classes (or ANY variable) to a stable state instead of relying on the compiler to do it for you; especially since some compilers deliberately fill them with garbage. In fact, the only POD MSVC++ doesn't fill with garbage is bool, they get initialized to true. One would think it'd be safer to init it to false, but that's Microsoft for ya.
Case 1
Regardless of whether the encapsulating type is POD, data members of a built-in type are not default initialised by an encapsulating default constructor.
Case 2
No, neither got initialised. The underlying bytes at the memory position of one of them just happened to be 0.
Case 3
Same.
You seem to be expecting some guarantees about the "value" of uninitialised objects, whilst simultaneously professing the understanding that no such value exists.
Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case?
And second question: Is it possible to specify default value to be used while initializing elements in the array? Something like this (not valid):
char* p = new char[size]('\0');
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type, every element of this array will be initialized with default value. Why is this?
If arrays for built in types do not initialize their elements with their defaults, why do they do it for User Defined Types?
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
I think that behaviour should be consistent, so either every type of array should be initialized or none. And I think that the behaviour for built-in arrays is more appropriate.
That's how built-in types work in C++. In order to initialize them you have to supply an explicit initializer. If you don't, then the object will remain uninitialized. This behavior is in no way specific to arrays. Standalone objects behave in exactly the same way.
One problem here is that when you are creating an array using new[], you options for supplying an initializer (in the current version of the language) are very limited. In fact, the only initializer you can supply is the empty ()
char* p = new char[size]();
// The array is filled with zeroes
In case of char type (or any other scalar type), the () initializer will result in zero-initialization, which is incidentally what you tried to do.
Of course, if your desired default value in not zero, you are out of luck, meaning that you have to explicitly assign the default values to the elements of the new[]-ed array afterwards.
As for disabling the default constructor call for arrays of types with user-defined default constructor... well, there's no way to achieve that with ordinary new[]. However, you can do it by implementing your own array construction process (which is what std::vector does, for one example). You first allocate raw memory for the entire array, and then manually construct the elements one-by-one in any way you see fit. Standard library provides a number of primitive intended to be used specifically for that purpose. That includes std::allocator and functions like uninitialized_copy, uninitialized_fill and so on.
Something like this (not valid):
As far as I know that is perfectly valid.
Well not completely, but you can get a zero intialized character array:
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[])
{
//The extra parenthesis on the end call the "default constructor"
//of char, which initailizes it with zero.
char * myCharacters = new char[100]();
for(size_t idx = 0; idx != 100; idx++) {
if (!myCharacters[idx])
continue;
std::cout << "Error at " << idx << std::endl;
std::system("pause");
}
delete [] myCharacters;
return 0;
}
This program produces no output.
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type and knowing the fact that every elem. of this array will be initialized with default value firstly why?
Because there's no good syntactic way to specialize each element allocated with new. You can avoid this problem by using a vector instead, and calling reserve() in advance. The vector will allocate the memory but the constructors will not be called until you push_back into the vector. You should be using vectors instead of user managed arrays anyway because new'd memory handling is almost always not exception safe.
I think that behaviour should be consistent, so either every type of array should be initialized or none. And I think that the behaviour for built-in arrays is more appropriate.
Well if you can think of a good syntax for this you can write up a proposal for the standard -- not sure how far you'll get with that.
Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case? and
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type, every element of this array will be initialized with default value. Why is this? and
If arrays for built in types do not initialize their elements with their defaults, why do they do it for User Defined Types?
Because a user defined type is never ever valid until its constructor is called. Built in types are always valid even if a constructor has not been called.
And second question: Is it possible to specify default value to be used while initializing elements in the array? Something like this (not valid):
Answered this above.
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
Yes, you can use a vector as I described above.
Currently (unless you're using the new C++0x), C++ will call the constructor that takes no arguments e.g. myClass::myClass(). If you want to initialise it to something, implement a constructor like this that initialises your variables. e.g.
class myChar {
public:
myChar();
char myCharVal;
};
myChar::myChar(): myCharVal('\0') {
}
The C++ philosophy is - don't pay for something you don't need.
And I think the behviour is pretty unified. If your UDT didn't have a default constructor, nothing would be run anyway and the behaviour would be the same as for built-in types (which don't have a default constructor).
Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case?
But if the default constructor of an object does nothing then it is still not initialiized.
class X
{
public:
char y;
}
X* data = new X[size]; // defaut constructor called. But y is still undefined.
And second question: Is it possible to specify default value to be used while initializing elements in the array? > Something like this (not valid):
Yes:
char data1[size] = { 0 };
std::vector<char> data2(size,0);
char* data3 = new char[size];
memset(data3,0,size);
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
Yes. Use a std::vector.
You can reserve the space for all the elements you need without calling the constructor.
std::vector<char> data4;
data4.reserve(size);
I noticed that when you declare an array, the default constructor must be needed. Is that right?
Is there any exception?
For example,
struct Foo{
Foo(int i ) {}
};
int main () {
Foo f[5];
return 0;
}
The code above does not compile.
Other answers are all right but, for completeness: You could also use the array initialization syntax:
Foo f[5] = {1,2,3,4,5};
This works if Foo's ctor is not explicit. If it was, you'd have to be.... explicit:
Foo f[5] = {Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)};
Note1: There is a difference between the two cases that may not be obvious and is thus worth noting: In the first, the array elements are directly constructed from the ints in the initialization list, by invoking the Foo(int) ctor. In the second, the initialization list is made of Foos constructed with the explicit Foo(int) ctor, and the array elements are copy constructed from the elements in the initialization list. A copy ctor for Foo is thus required in the latter case.
[1] Thanks to MSalters for the comment.
The issue has nothing to do with arrays at all.
When you default-initialize an object of class type, the default constructor is required. If your class has no default constructor, then you have no other choice but to supply an explicit initializer when creating objects of that class. That's all.
By declaring a non-default constructor in your class Foo, you disabled the implicit generation of the default one, so now you'll have to supply an initializer every time you create a Foo object, regardless of whether it is an array element or not.
This declaration
Foo f; // ERROR
is not an array, but it will not compile for the very same reason. In order for it to compile you'll have to supply an explicit initializer
Foo f(3); // OK
The same thing happens with array, except that in that case you have to supply an initializer for each element using the aggregate initializer syntax
Foo f[5] = { 1, 2, 3, 4, 5 };
Of course, if you end up in a context where aggregate initializer syntax is not allowed (in the current version of C++ standard), like constructor initializer list or new-expression, then you are indeed screwed. In such contexts the only way out is to provide the default constructor in array element type (as long as you stick with built-in arrays).
That code doesn't compile because the compiler doesn't know what you want to pass to the constructor of each element, of course. There are basically two ways to go about it:
Make the array a vector, and pass it the desired size plus a single element -- this gives each element the same argument.
Make the array an array of pointers, and construct each element using a for loop and the new operator. The drawback of course, is that you have to free each element later as well.
See the C++ FAQ Lite, section 10.5
When you create an array, the default constructor gets called for each element in the array.
"If your class doesn't have a default constructor, you'll get a compile-time error when you attempt to create an array "
Prefer to use std::vector instead of the built-in arrays, though.
There is no exception. In what could be seen as exception, there is a compiler declared default constructor.
Note that a default constructor is not required if you use std::vector instead of an array - you can specify the constructor to be used:
std::vector <Foo> f; // OK
std::vector <Foo> f( 5, Foo(0) ); // also OK
No it doesn't.
An array, in C/C++ is a block of memory. Creating an array is reserving that block. Creating the objects is "1. Allocating the space 2. Running the constructors on each block" So, if you have an object without a constructor, you can still make an array of it (since that object has a size and since memory understands "size").
In short, it doesn't make any difference whatsoever. You will be running the constructors as you create the objects to fill the array with, or as said previously, when you assign it to something (which in turn, allocates space, runs the constructor).
Yes, you need the default constructor here because Foo f[5]; actually creates 5 Foos. You can work around this by making it a Foo* f[5] and then creating the 5 Foos with new.
For example:
Foo* f[5];
for(int i = 0; i < 5; ++i) {
f[i] = new Foo(i);
}
// later on...
f[0]->whatever();
Warning: slightly off-topic.
If you have a class without default constructor, you absolutely need to have an array, and you don't want to incur into the overhead of dynamic memory allocation, you can use an array of boost::optionals:
boost::optional<Foo> foos[4]; // Stack storage allocated but no objects
// constructed (roughly equivalent to what
// you get with vector<T>::reserve)
if(foos[2]) // Check if the third element has been constructed
{
foos[2]->bar(); // Access members of Foo with arrow
}
foos[1] = Foo(1, "a"); // Constructs the second element
foos[1].reset(); // Destroy second element (storage remains there though)
Unfortunately, you won't be able to pass this to a function expecting a true Foo[].