I wrote the following code snippet:
void foo()
{
struct _bar_
{
int a;
} bar;
cout << "Value of a is " << bar.a;
}
and compiled it with g++ 4.2.1 (Mac). The output is "Value of a is 0".
Is it true to say that data members of a struct in c++ are always initialized by default (compared to c)? Or is the observed result just coincidence?
I can imagine that structs in c++ have a default constructor (since a struct and a class is almost the same in c++), which would explain why the data member a of bar is initialized to zero.
The simple answer is yes.
It has a default constructor.
Note: struct and class are identical (apart from the default state of the accesses specifiers).
But whether it initializes the members will depends on how the actual object is declared. In your example no the member is not initialized and a has indeterminate value.
void func()
{
_bar_ a; // Members are NOT initialized.
_bar_ b = _bar_(); // Members are zero-initialized
// From C++14
_bar_ c{}; // New Brace initializer (Members are zero-initialized)
_bar_* aP = new _bar_; // Members are NOT initialized.
_bar_* bP = new _bar_(); // Members are zero-initialized
// From C++14
_bar_ cP = new _bar_{}; // New Brace initializer (Members are zero-initialized)
}
// static storage duration objects
// i.e. objects at the global scope.
_bar_ c; // Members are zero-initialized.
The exact details are explained in the standard at 8.5 Initializers [dcl.init] paragraphs 4-10. But the following is a simplistic summary for this situation.
A structure without a user defined constructor has a compiler generated constructor. But what it does depends on how it is used and it will either default initialize its members (which for POD types is usually nothing) or it may zero initialize its members (which for POD usually means set its members to zero).
PS. Don't use a _ as the first character in a type name. You will bump into problems.
Is it true to say that data members of a struct in c++ are always initialized by default (compared to c)? Or is the observed result just coincidence?
It is a coincidence.
Your code invokes Undefined Behavior; unless you explicitly set the members to 0 they can be anything.
Not an answer, but you might take it to be... if you want to try it:
void foo() {
struct test {
int value;
} x;
std::cout << x.value << std::endl;
x.value = 1000;
}
int main() {
foo();
foo();
}
In your example, the memory already had the 0 value before the variable was created, so you can call it a lucky coincidence (in fact, some OS will zero out all memory before starting a process, which means that 0 is quite a likely value to find in a small short program...), the previous code will call the function twice, and the memory from the first call will be reused in the second one, chances are that the second time around it will print 1000. Note however that the value is still undefined, and that this test might or not show the expected result (i.e. there are many things that the compiler can do and would generate a different result...)
Member variables of a struct are not initialized by default. Just like a class (because a struct is exactly the same thing as a class, only in struct the members are public by default).
Do not rely on this functionality it is non-standard
just add
foo() : a() {}
I can't remember the exact state of gcc 4.2 (i think it is too old) but if you were using C++11 you can do the following
foo()=default;
Related
Since C++14 (it might be C++11, i'm not sure), zero initialization happens on class construction on certain conditions, depending on the way the constructor is called.
Is there a way to ensure a raw value field (let's say a pointer) is never zero initialized ?
I guess not because it seems that zero initialization happens at the class level and not at the field level (surely a kind of memset(this, 0, sizeof(TheClass))), but I'm still hoping there is way, a hack, something...
The idea is to be able to initialize a field before a placement new is called so that that member is available during construction time.
According to cppreference's take on zero initialization:
If T is an non-union class type, all base classes and non-static data
members are zero-initialized, and all padding is initialized to zero
bits. The constructors, if any, are ignored.
If your object is a victim of zero initialization you're out of luck. And every object with static or thread local storage duration will always be zero initialized (except for constant initialization).
Is there a way to ensure a raw value field (let's say a pointer) is never zero initialized ?
It is possible, yes.
If the class is trivially default constructible, then simply default initialise the object, and its members will be default initialised as well:
int main() {
T t; // default initialised
If the class is not trivially default constructible, you can write a user defined constructor that leaves the member uninitialised (note that doing this is generally discouraged):
struct S {
int member;
S(){} // member is left default initialised
Warning: With a user defined constructor, the member would be left default initialised even if the object is value initialised.
Objects with static storage duration are always zero or constant initialised. Neither of those leave members uninitialised. Only way to avoid that initialisation is to not create objects with static storage duration.
The idea is to be able to initialize a field before a placement new is called so that that member is available during construction time.
If you mean your idea is to initialise a field of an object that hasn't yet been created with placement new, then the idea is not possible to implement.
Members are available during construction time. You don't need any tricks to achieve this. All members that can be used by their siblings in order of their initialisation. And the constructor body is run after all members have been initialised.
As #eerorika's answer suggests:
struct S {
int member;
S(){} // member is left default initialised
...note that doing this is generally discouraged
I would say that the clearest way to achieve this without confusing the user of the class would be not to use a int, but a std::aligned_storage_t as it is clear that this member is used just for storage of objects that might be created later rather than a value that can be used on its own.
Depending how much code you would like to write, this might be tedious, because you have to write placement news and use std::launder (since c++17) to be compliant with the standard. However, this is IMO the best way to express your intent.
cppreference gives a good example of how to use std::aligned_storage (with some modification, see comments):
#include <iostream>
#include <type_traits>
#include <string>
template<class T, std::size_t N>
class static_vector
{
// properly aligned uninitialized storage for N T's
typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
std::size_t m_size = 0;
public:
// My modification here suppresses zero-initialization
// if initialized with empty braces
static_vector() {};
// Create an object in aligned storage
template<typename ...Args> void emplace_back(Args&&... args)
{
if( m_size >= N ) // possible error handling
throw std::bad_alloc{};
// construct value in memory of aligned storage
// using inplace operator new
new(&data[m_size]) T(std::forward<Args>(args)...);
++m_size;
}
// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
// note: needs std::launder as of C++17
return *reinterpret_cast<const T*>(&data[pos]);
}
// Delete objects from aligned storage
~static_vector()
{
for(std::size_t pos = 0; pos < m_size; ++pos) {
// note: needs std::launder as of C++17
reinterpret_cast<T*>(&data[pos])->~T();
}
}
};
int main()
{
static_vector<std::string, 10> v1;
v1.emplace_back(5, '*');
v1.emplace_back(10, '*');
std::cout << v1[0] << '\n' << v1[1] << '\n';
static_vector<std::size_t, 10> v2{};
// This is undefined behavior.
// Here it's just used to demonstrate that
// the memory is not initialized.
std::cout << v2[0] << "\n";
}
Run it on compiler explorer
However, since the c++ standard only mandates when zero-initialization must happen, but not when it must not happen, sometimes you really have to wrestle with your compiler in order to suppress zero initialization.
See this question and this question for more details.
Does the default constructor (created by the compiler) initialize built-in-types?
Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.
However, you have to keep in mind that in some cases the initialization of a instance of the class can be performed by other means. Not by default constructor, nor by constructor at all.
For example, there's a widespread incorrect belief that for class C the syntax C() always invokes default constructor. In reality though, the syntax C() performs so called value-initialization of the class instance. It will only invoke the default constructor if it is user-declared. (That's in C++03. In C++98 - only if the class is non-POD). If the class has no user-declared constructor, then the C() will not call the compiler-provided default constructor, but rather will perform a special kind of initialization that does not involve the constructor of C at all. Instead, it will directly value-initialize every member of the class. For built-in types it results in zero-initialization.
For example, if your class has no user-declared constructor
class C {
public:
int x;
};
then the compiler will implicitly provide one. The compiler-provided constructor will do nothing, meaning that it will not initialize C::x
C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage
Nevertheless, the following initializations will zero-initialize x because they use the explicit () initializer
C c = C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(c.x == 0);
C *pc = new C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(pc->x == 0);
The behavior of () initializer is different in some respects between C++98 and C++03, but not in this case. For the above class C it will be the same: () initializer performs zero initialization of C::x.
Another example of initialization that is performed without involving constructor is, of course, aggregate initialization
C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);
C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);
I'm not quite certain what you mean, but:
struct A { int x; };
int a; // a is initialized to 0
A b; // b.x is initialized to 0
int main() {
int c; // c is not initialized
int d = int(); // d is initialized to 0
A e; // e.x is not initialized
A f = A(); // f.x is initialized to 0
}
In each case where I say "not initialized" - you might find that your compiler gives it a consistent value, but the standard doesn't require it.
A lot of hand-waving gets thrown around, including by me, about how built-in types "in effect" have a default constructor. Actually default initialization and value initialization are defined terms in the standard, which personally I have to look up every time. Only classes are defined in the standard to have an implicit default constructor.
For all practical purposes - no.
However for implementations that are technically compliant with the C++ standard, the answer is that it depends whether the object is POD or not and on how you initialize it.
According to the C++ standard:
MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized
However, in the real world, this isn't well supported so don't use it.
The relevant parts of the standard are section 8.5.5 and 8.5.7
As per the standard, it doesn't unless you explicitly initialize in initializer list
As previous speakers have stated - no, they are not initialized.
This is actually a source for really strange errors as modern OSs tend to fill newly allocated memory regions with zeroes. If you expect that, it might work the first time. However, as your application keeps running, delete-ing and new-ing objects, you will sooner or later end up in a situation where you expect zeroes but a non-zero leftover from an earlier object sits.
So, why is this then, isn't all new-ed data newly allocated? Yes, but not always from the OS. The OS tends to work with larger chunks of memory (e.g. 4MB at a time) so all the tiny one-word-here-three-bytes-there-allocations and deallocations are handled in uyserspace, and thus not zeroed out.
PS. I wrote "tend to", i.e. you can't even rely on success the first time...
Technically it does initialize them -- by using their default constructor, which incidentally does nothing but allocate the memory for them.
If what you wanted to know is whether or not they are set to something sane like 0 for ints, then the answer is "no".
No. The default constructor allocates memory and calls the no-argument constructor of any parents.
Does the default constructor (created by the compiler) initialize built-in-types?
Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.
However, you have to keep in mind that in some cases the initialization of a instance of the class can be performed by other means. Not by default constructor, nor by constructor at all.
For example, there's a widespread incorrect belief that for class C the syntax C() always invokes default constructor. In reality though, the syntax C() performs so called value-initialization of the class instance. It will only invoke the default constructor if it is user-declared. (That's in C++03. In C++98 - only if the class is non-POD). If the class has no user-declared constructor, then the C() will not call the compiler-provided default constructor, but rather will perform a special kind of initialization that does not involve the constructor of C at all. Instead, it will directly value-initialize every member of the class. For built-in types it results in zero-initialization.
For example, if your class has no user-declared constructor
class C {
public:
int x;
};
then the compiler will implicitly provide one. The compiler-provided constructor will do nothing, meaning that it will not initialize C::x
C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage
Nevertheless, the following initializations will zero-initialize x because they use the explicit () initializer
C c = C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(c.x == 0);
C *pc = new C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(pc->x == 0);
The behavior of () initializer is different in some respects between C++98 and C++03, but not in this case. For the above class C it will be the same: () initializer performs zero initialization of C::x.
Another example of initialization that is performed without involving constructor is, of course, aggregate initialization
C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);
C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);
I'm not quite certain what you mean, but:
struct A { int x; };
int a; // a is initialized to 0
A b; // b.x is initialized to 0
int main() {
int c; // c is not initialized
int d = int(); // d is initialized to 0
A e; // e.x is not initialized
A f = A(); // f.x is initialized to 0
}
In each case where I say "not initialized" - you might find that your compiler gives it a consistent value, but the standard doesn't require it.
A lot of hand-waving gets thrown around, including by me, about how built-in types "in effect" have a default constructor. Actually default initialization and value initialization are defined terms in the standard, which personally I have to look up every time. Only classes are defined in the standard to have an implicit default constructor.
For all practical purposes - no.
However for implementations that are technically compliant with the C++ standard, the answer is that it depends whether the object is POD or not and on how you initialize it.
According to the C++ standard:
MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized
However, in the real world, this isn't well supported so don't use it.
The relevant parts of the standard are section 8.5.5 and 8.5.7
As per the standard, it doesn't unless you explicitly initialize in initializer list
As previous speakers have stated - no, they are not initialized.
This is actually a source for really strange errors as modern OSs tend to fill newly allocated memory regions with zeroes. If you expect that, it might work the first time. However, as your application keeps running, delete-ing and new-ing objects, you will sooner or later end up in a situation where you expect zeroes but a non-zero leftover from an earlier object sits.
So, why is this then, isn't all new-ed data newly allocated? Yes, but not always from the OS. The OS tends to work with larger chunks of memory (e.g. 4MB at a time) so all the tiny one-word-here-three-bytes-there-allocations and deallocations are handled in uyserspace, and thus not zeroed out.
PS. I wrote "tend to", i.e. you can't even rely on success the first time...
Technically it does initialize them -- by using their default constructor, which incidentally does nothing but allocate the memory for them.
If what you wanted to know is whether or not they are set to something sane like 0 for ints, then the answer is "no".
No. The default constructor allocates memory and calls the no-argument constructor of any parents.
Does the default constructor (created by the compiler) initialize built-in-types?
Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.
However, you have to keep in mind that in some cases the initialization of a instance of the class can be performed by other means. Not by default constructor, nor by constructor at all.
For example, there's a widespread incorrect belief that for class C the syntax C() always invokes default constructor. In reality though, the syntax C() performs so called value-initialization of the class instance. It will only invoke the default constructor if it is user-declared. (That's in C++03. In C++98 - only if the class is non-POD). If the class has no user-declared constructor, then the C() will not call the compiler-provided default constructor, but rather will perform a special kind of initialization that does not involve the constructor of C at all. Instead, it will directly value-initialize every member of the class. For built-in types it results in zero-initialization.
For example, if your class has no user-declared constructor
class C {
public:
int x;
};
then the compiler will implicitly provide one. The compiler-provided constructor will do nothing, meaning that it will not initialize C::x
C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage
Nevertheless, the following initializations will zero-initialize x because they use the explicit () initializer
C c = C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(c.x == 0);
C *pc = new C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(pc->x == 0);
The behavior of () initializer is different in some respects between C++98 and C++03, but not in this case. For the above class C it will be the same: () initializer performs zero initialization of C::x.
Another example of initialization that is performed without involving constructor is, of course, aggregate initialization
C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);
C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);
I'm not quite certain what you mean, but:
struct A { int x; };
int a; // a is initialized to 0
A b; // b.x is initialized to 0
int main() {
int c; // c is not initialized
int d = int(); // d is initialized to 0
A e; // e.x is not initialized
A f = A(); // f.x is initialized to 0
}
In each case where I say "not initialized" - you might find that your compiler gives it a consistent value, but the standard doesn't require it.
A lot of hand-waving gets thrown around, including by me, about how built-in types "in effect" have a default constructor. Actually default initialization and value initialization are defined terms in the standard, which personally I have to look up every time. Only classes are defined in the standard to have an implicit default constructor.
For all practical purposes - no.
However for implementations that are technically compliant with the C++ standard, the answer is that it depends whether the object is POD or not and on how you initialize it.
According to the C++ standard:
MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized
However, in the real world, this isn't well supported so don't use it.
The relevant parts of the standard are section 8.5.5 and 8.5.7
As per the standard, it doesn't unless you explicitly initialize in initializer list
As previous speakers have stated - no, they are not initialized.
This is actually a source for really strange errors as modern OSs tend to fill newly allocated memory regions with zeroes. If you expect that, it might work the first time. However, as your application keeps running, delete-ing and new-ing objects, you will sooner or later end up in a situation where you expect zeroes but a non-zero leftover from an earlier object sits.
So, why is this then, isn't all new-ed data newly allocated? Yes, but not always from the OS. The OS tends to work with larger chunks of memory (e.g. 4MB at a time) so all the tiny one-word-here-three-bytes-there-allocations and deallocations are handled in uyserspace, and thus not zeroed out.
PS. I wrote "tend to", i.e. you can't even rely on success the first time...
Technically it does initialize them -- by using their default constructor, which incidentally does nothing but allocate the memory for them.
If what you wanted to know is whether or not they are set to something sane like 0 for ints, then the answer is "no".
No. The default constructor allocates memory and calls the no-argument constructor of any parents.
Just a simple question about c++ coding style,
for example, all member variables of a class will be called with the default constructor in the initialization list if we don't do anything else. B default constructor will be called and value will be set to 0, int();
class A
{
A();
private:
B b;
int value;
}
However my question is, even do the default constructor will be called is it a good habit to always do it yourself or does it only add extra lines to the code
A::A() : b(), value() {}
You are touching on one of the sticky corners of C++.
The initialization of POD values in objects is sticky and depends on a few things.
Even I am not sure I can get all the rules correct but I believe #Steve Jessop once wrote an article about here on SO (though I can currently find it).
But some examples:
This class will always be initialized b == false and value = 0.
class A
{
A() : b(), value() {}
B b;
int value;
};
Without an explicit default constructor it is more complex:
Here the compiler will generate a default constructor for you. But how the compiler generated default constructor works depends on the situation. The compiler generated default constructor can do two different forms of initialization and which is used depends on context:
Zero Initialization (All POD members are zero'ed out)
Value Initialization (All POD members are left undefined)
Example:
class B
{
B b;
int value;
};
// Variables of static storage duration (notably globals)
// Will be zero initialized and thus b == false and value = 0
B global; // Initialized
int main()
{
// Object of automatic storage duration or dynamic storage duration
// These will depend on how they are declared.
// Value Initialization (POD re-mains undefined)
B bo1; // b/value undefined
B* bp1 = new B; // b.balue undefined
// Zero Initialization
B bo2 = B(); // b = false, value = 0
B* bp2 = new B(); // b = false, value = 0
// Note: The most obvious syntax for zero initializing a local object
// does not work as it is actually interpreted as a forward
// declaration of a function;
B bo3();
}
It's a good idea to leave the default constructor out. The compiler-generated constructors are much more reliable and maintainable than writing your own versions, and apart from anything else, it's a flat out waste of time to write code the compiler could write for you. If you don't need any construction logic, then don't write a constructor.
However, the int will not be initialized unless you do it, which is a sucky reason to have to write a constructor.
By default int variables are not initialized with a value - you have to do it yourself.
So when you don't set the member variable "value" to some value in the constructor it is left uninitialized.
The default constructor will only be called for class types with default constructors, not for primitives.