Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - order of member initialization and incrementation

I was looking for some tests to improve my C++ knowledge. Here is one of the exercises: What is the output of the following program?

#include <iostream>

class A
{
public:
    A(int n = 0) : m_i(n)
    {
        std::cout << m_i;
        ++m_i;
    }

protected:
    int m_i;
};

class B : public A
{
public:
    B(int n = 5) : m_a(new A[2]), m_x(++m_i) { std::cout << m_i; }

    ~B() { delete [] m_a; }

private:
    A m_x;
    A *m_a;
};

int main()
{
    B b;
    std::cout << std::endl;
    return 0;
}

Well, I tried this code, and the answer is 02002. I come here to have some explanation because I don't understand why 02002 is the result. I will explain my reasoning, but could some tell me where am I wrong please?

Let's call "str" the current string to print. When the b object is built:

  1. The constructor of A is called. str => 0, m_i => 1
  2. Construction of m_a(new A[2]). str => 000
  3. Construction of m_x(++m_i). str => 0002, m_i => 3
  4. Last update of str (in B's constructor) => str => 00023

Here are my questions:

  • Why is the final value of m_i 2 and not 3?
  • Why is the construction of m_x(++m_i) done before the one of m_a(new A[2])? I tried to exchange the position of the initialization of m_x and m_a and the answer is still the same : 02002.
like image 232
Ptiseb Avatar asked Dec 23 '15 16:12

Ptiseb


2 Answers

Why is the final value of m_i 2 and not 3?

Because new A[2] creates two separate instances having nothing to do with *this. m_i of the b instance is only incremented in A::A and B::B (twice).

If incrementation of m_i should be performed on the same instance (m_i being a reference, for example), it would be more reasonable to think that the final value of m_i should be 4 (there are two objects in the array - two additional increments).

Why is the construction of m_x(++m_i) done before the one of m_a(new A[2])?

Because the order of initialization depends on the order of declaration of the data members, not the order in which you write initializations in the member initializer list.

like image 66
LogicStuff Avatar answered Oct 21 '22 19:10

LogicStuff


When you construct b the A part of B is constructed first. This gives the 0 in the output. Then we get the 2 because m_x(++m_i) happens first since m_x is listed first in the class. Since m_i is 1 from the A part of B being constructed ++m_i gives 2 and now we have 02. Then m_a(new A[2]) is ran which gives us 2 0(one for each memeber of the array). That puts us at 0200. We then get the final 2 from { std::cout << m_i; } since m_i is still 2 from m_x(++m_i).

like image 37
NathanOliver Avatar answered Oct 21 '22 18:10

NathanOliver