56

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.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
morpheus
  • 563
  • 1
  • 4
  • 4
  • 1
    As also pointed out, it's a coincidence. Note that you can always zero-initialize the struct with `bar = {}`. – avakar Nov 26 '11 at 17:07

5 Answers5

71

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 depend 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.

Robert Hacken
  • 3,878
  • 1
  • 13
  • 15
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 1
    One underscore is fine, unless followed by another underscore or a capital. – rubenvb Nov 26 '11 at 18:26
  • 1
    I selected this answer because it best answered my question. It also provides additional information about when a default constructor is zero-initializing data members. – morpheus Nov 26 '11 at 18:46
  • 6
    @rubenvb: Actually that's not true. Read: [what-are-the-rules-about-using-an-underscore-in-a-c-identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797) The problem is that most people do not know the exact rules and make mistakes just like that. So best to avoid them at the beginning of identifiers. Here: An underscore followed by any letter is reserved in the global scope. – Martin York Nov 26 '11 at 18:56
  • Does this work if the structure contains objects, etc. It should recursively call the constructor of the respective members also right? – Shravya Boggarapu Nov 27 '17 at 05:59
  • 1
    @ShravyaBoggarapu: Yes. **Note-1:** If an object id **zero-initialized** it wall call the default constructor of any object member. If that object does not have an explicit constructor then it will **zero-initialize** using the compiler generated constructor. **Note-2:** If an object id **default-initialized** it wall call the default constructor of any object member. If that object does not have an explicit constructor then it will **default-initialize** using the compiler generated constructor. – Martin York Nov 27 '17 at 21:53
  • See comment of @DavidRodríguez below, because in different places **bar.a can has different value**. Also you can read this https://stackoverflow.com/questions/17106389/initializing-member-variables-of-a-struct-in-c – 0x000f Oct 31 '18 at 07:51
  • @0x000f Not sure how that adds anything. This answer already covers all those situations! – Martin York Oct 31 '18 at 15:32
  • @Martin York There are answers on question "Initializing member variables of a struct in c++". It may be useful to read the answers if you have question "Is it true to say that data members of a struct in c++ are always initialized by default?". – 0x000f Dec 07 '18 at 06:32
  • @MartinYork do you know in what part of the standard is described what happens with `_bar_* bP = new _bar_();`? Thank you. – Alessandro Jacopson Mar 27 '19 at 12:37
  • 1
    @AlessandroJacopson: in `n4800`. Section 10.9 Paragraph 1 Which tells you to read Section 9.3. In Section 9.3 Paragraph 11 `An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.` Then Value Initialization is defined in Section 9.3 Paragraph 8.2. `if T is a ... class type without a user-provided or deleted default constructor, then the object is zero-initialized` Then Zero Initialization is defined in Section 9.3 Paragraph 6.2 `if T is a ... non-union class type, its padding bits (6.7) are initialized to zero bits` – Martin York Mar 27 '19 at 15:10
  • 1
    @AlessandroJacopson You can download the latest version of the standard here. Its relatively easy to search the PDF. https://stackoverflow.com/a/4653479/14065 – Martin York Mar 27 '19 at 15:15
  • "The standard specifies that zero-initialization is not performed when the class has a user-provided or deleted default constructor, even if that default constructor is not selected by overload resolution. All known compilers performs additional zero-initialization if a non-deleted defaulted default constructor is selected." Thus, if you specify a non-default constructor and it gets used, you can still prevent or control initialization of members. https://en.cppreference.com/w/cpp/language/value_initialization – Andrew Jun 16 '21 at 05:08
12

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.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Alok Save
  • 202,538
  • 53
  • 430
  • 533
4

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...)

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
3

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).

Igor
  • 26,650
  • 27
  • 89
  • 114
0

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;
Alok Save
  • 202,538
  • 53
  • 430
  • 533
111111
  • 15,686
  • 6
  • 47
  • 62