12

Before you start to mark this as duplicate I've already read this .But It doesn't answer my question. The linked question talks about C++98 & C++03 but my question is about defaulted constructor introduced by C++11.

Consider following program (See live demo here):

#include <iostream>
struct Test
{
    int s;
    float m;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
}t;
int main()
{
    std::cout<<t.s<<'\n';
    std::cout<<t.m<<'\n';
}

My question is that is the defaulted constructor provided by compiler here always initializes built in types to by default 0 in C++11 & C++14 when they are class & struct members. Is this behavior guaranteed by C++11 standard?

Community
  • 1
  • 1
Destructor
  • 14,123
  • 11
  • 61
  • 126
  • Who voted to close? Why? – Destructor Oct 30 '15 at 16:55
  • 4
    see the [wiki's entry on default-initialization](http://en.cppreference.com/w/cpp/language/default_initialization) – jaggedSpire Oct 30 '15 at 16:56
  • 7
    However, you declared `t` as a global, so it would be value/zero initialized anyway IIRC – melak47 Oct 30 '15 at 16:57
  • 1
    @PravasiMeet _"Who voted to close? Why?"_ Regarding the _why_, you've got enough rep to check yourself. But I agree it's a valid and valuable question. I've just been falling into the same pit, with my (now removed) comment. – πάντα ῥεῖ Oct 30 '15 at 17:03
  • @πάνταῥεῖ: how to check that? I really don't know. – Destructor Oct 30 '15 at 17:06
  • @PravasiMeet Just click the [_close_](http://stackoverflow.com/questions/33441087/is-it-guaranteed-that-defaulted-constructor-initialize-built-in-types-automatica?noredirect=1#) link yourself, and you can see what was marked. – πάντα ῥεῖ Oct 30 '15 at 17:09
  • @melak47 How are default and value init different for `Test`? – curiousguy Oct 30 '15 at 17:31
  • No. When you default a special member you don't get any different behavior than if the special member were implicitly provided. Built-in types, by default, will have whatever value was left in the memory previously (random (but not cryptographically so) for auto and free-store, 0 for statically allocated). To get them zero-initialized you must define the default constructor to do so, such as by including `s(),m()` in the initializer list. – John Oct 30 '15 at 17:56

5 Answers5

17

There are two separate questions built into this question.

  1. What does = default mean for the default constructor? From [class.ctor]:

    A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement.

    That is, Test() = default is exactly equivalent to Test() { }, which would default-initialize s and m, which sets them to some indeterminate value.

  2. How are t.s and t.m initialized? Yes, this is a separate question from (1) because we're not just calling the default constructor here. From [basic.stc.static]:

    All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration.

    and from [basic.start.init]:

    Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.

    Thus t.s and t.m are guaranteed to be 0, even though if we default-constructed a local Test, they would not be.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Does this work for union members? Does this make sense? – curiousguy Oct 30 '15 at 17:35
  • @curiousguy Zero-initialization for a union means "the object’s first non-static named data member is zero-initialized and padding is initialized to zero bits;" – Barry Oct 30 '15 at 18:17
  • 3
    "Test() = default is exactly equivalent to Test() { }": nearly right, it is potentially *trivial* though. And you *want* your constructors and destructors be *trivial* whenever you can. – Deduplicator Oct 30 '15 at 18:33
  • Is the static-storage zero-initialization of s and m guarenteed to survive the constructor call? I.e., if a constructor does not initialize a member, does that mean "the memory contained the member is unchanged" or does it mean that "the compiler can do whatever it likes"? – user1998586 Oct 30 '15 at 20:02
  • @Barry So "Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place"? don't apply to union members? – curiousguy Oct 31 '15 at 13:52
  • @user1998586 Do builtin type objects survive ctors/dtors? This was my (heavily downvoted) question [here](http://stackoverflow.com/questions/11637611/after-an-object-is-destroyed-what-happens-to-subobjects-of-scalar-type) – curiousguy Oct 31 '15 at 13:57
  • @curiousguy It does apply to union members in a way that makes sense: the first member is made active and is zero-initialized. You cannot talk about initializing "all members" of a union, because they share the same memory. – Sebastian Redl Mar 31 '17 at 07:13
8

Test = default will default initialize its members. but for type as int or float, default initialization is different than value-initialization

so

Test t; // t.s and t.m have unitialized value

whereas

Test t{}; // t.s == 0 and t.m == 0.0f;
Jarod42
  • 203,559
  • 14
  • 181
  • 302
6

As it is already answered, it is not guaranteed that default constructor will "initialize built in types automatically to 0".

You can use placement new to see this for yourself. Consider the following code:

#include <iostream>

struct Test
{
    int s;
    float m;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
};

int main()
{
    char* buf = new char[sizeof(Test)];
    Test* t = new (buf) Test;

    std::cout << t->s << '\n';
    std::cout << t->m <<'\n';

    t->s = 42;
    t->m = 4.2;

    t->~Test();
    t = new (buf) Test;

    std::cout << t->s << '\n';
    std::cout << t->m <<'\n';
}

If default constructor was guaranteed to zero-initialize data members on non-class types, the output of this program would be four zeroes.

However, you'll likely see something like this instead:

0
0
42
4.2

Here's this code on cpp.sh - http://cpp.sh/9fdj

Nikita Kakuev
  • 1,096
  • 9
  • 13
  • Nice trick to test default/value init, but notice the OP has a `t` with different storage type, which changes the answer. – ricab Mar 08 '18 at 18:49
3

No, the default constructor doesn't do anything! To initialize the member variables you can write:

struct Test
{
    int s = 0;
    float m = 3.3;
    Test(int a,float b) : s(a),m(b)
    { }
    Test()=default;
};

Look at this: C++ ctor = default

Community
  • 1
  • 1
Elvis Dukaj
  • 7,142
  • 12
  • 43
  • 85
2

For all purposes:

Test() = default;

is equivalent to:

Test() {}

So it does not initialize members of built-in types.

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • 3
    What does "for all purposes" mean? – Columbo Oct 30 '15 at 16:59
  • 1
    Not the same if trivially constructible is one of those purposes – Praetorian Oct 30 '15 at 17:01
  • 2
    I really don't think this is true. `Test()=default` would lead to value initialization of `Test` resulting in zero initialization of `s` and `m`. `Test() {}` would break that. – juanchopanza Oct 30 '15 at 17:03
  • 5
    @juanchopanza 12.1 "The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no _ctor-initializer_ and an empty _compound-statement_." – aschepler Oct 30 '15 at 17:05
  • @aschepler Maybe that refers to default initialization. As far as I can see from the C++11 standard, the behaviour under value initialization is different. – juanchopanza Oct 30 '15 at 17:16
  • 4
    Ah yes, value initialization's behavior depends on whether there's a "user-provided" constructor, so there `Test()=default;` is different from `Test() {}`. – aschepler Oct 30 '15 at 17:29