2

I am mainly confused by the notion of different initialization in c++, particularly in standard.

I am specifically confused by the case where the object is constructed through new (relevant or not), and a list of initializers (which matches a user-defined constructor) are supplied, and that constructor does not initialize all members (including PODs and other classes).

The following demonstrates my confusion.

class B
{
public:
    int b1;
    int b2;
};

class C
{
public:
    int c1;
    int c2;
    C()
    {
        c2 = 1234;
    }
};

class A
{
public:
    int a1;
    B a2;
    C a3;
    A(int a): a1(a){}
};

Now if I write auto aptr = new A(5), can we comment on

  1. what will be the value of each fields in aptr->a1, aptr->a2, aptr->a3?

  2. what initialization is triggered during this process?


Supplementary: A part of the confusion comes from the example included in https://en.cppreference.com/w/cpp/language/zero_initialization

struct A
{
    int i;
    A() { } // user-provided default ctor, does not initialize i
};

struct B { A a; }; // implicitly-defined default ctor

std::cout << B().a.i << '\n'; // value-initializes a B temporary
                              // leaves b.a.i uninitialized in C++03
                              // sets b.a.i to zero in C++11
// (note that B{}.a.i leaves b.a.i uninitialized in C++11, but for 
// a different reason: in post-DR1301 C++11, B{} is aggregate-initialization,
// which then value-initializes A, which has a user-provided ctor)

Where the value initialization of B seems to trigger A's certain initialization (which one is it) that sets A.i. Any comment on this one?

2
  • For me, I would just ALWAYS define constructors that initialize ALL members and then you don't have to worry about what the compiler may or may not do. Commented Oct 10, 2019 at 21:49
  • Thanks - I understand. But it would be good to know the actual rules. Commented Oct 10, 2019 at 22:33

1 Answer 1

1

What will be the value of each fields in aptr->a1, aptr->a2, aptr->a3?

  • aptr->a1 will have 5 : because of A(int a): a1(a){} and you pass A(5).
  • aptr->a2 will be a default (compiler gnerated) constructed B object(i.e. aggregate type) having its b1 and b2 garbage value.
  • aptr->a3 will be a C object constructed by the default constructor provided by you (i.e. C(){ c2 = 1234; }). Meaning c1 in a3 will have garbage value, and the c2 will be initlized with 1234.
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, would you explain the code example in the supplement of the question?
@LiangLuo That itself makes me confusing and that is why I did not consider in my answer. ;) On the other hand, if you are using c++11 or latter the latter case seems to be something important in the given comments. If you want specific reasoning about the code example, I would suggest asking a different question focussing only on it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.