ubadub
ubadub

Reputation: 3880

Can a member variable access the value of a previously defined member variable in the same initialization list (C++)?

For example:

Cls::Cls(int *p) : m1_(1), m2_(m1), m3_(p), m4_(m3) {}

where Cls::m1_ and Cls::m2_ are of type int and m3 and m4 are of type int*.

Is this legal? If it is legal, does it do what one would expect?

Upvotes: 2

Views: 90

Answers (3)

Peter
Peter

Reputation: 1611

Yes, it's legal. The init order follows the order of the members in the class.

struct C
{
    C() : m1_(1), m2_(m1_ + 1), m3_(m2_ + 2), m4_(m3_ + 3) {} 

    int m1_ = 0;
    int m2_ = 0;
    int m3_ = 0;
    int m4_ = 0;
};

int main()
{
    C c;
    std::cout << c.m1_ << std::endl;
    std::cout << c.m2_ << std::endl;
    std::cout << c.m3_ << std::endl;
    std::cout << c.m4_ << std::endl;
}

The output:

1
2
4
7

But if you modified the member orders:

struct C
{
    C() : m1_(1), m2_(m1_ + 1), m3_(m2_ + 2), m4_(m3_ + 3) {} 

    int m2_ = 0;
    int m3_ = 0;
    int m4_ = 0;
    int m1_ = 0;
};

The output will be:

1
1
3
6

Upvotes: 3

NathanOliver
NathanOliver

Reputation: 180490

This is legal-ish. If you have

struct foo
{
    int a;
    int b;
    int c;
    foo() : a(1), b(a + 1), c(b + 1) {}
};

Then this is fine. The reason is a is declared in the class before b and b is declared before c. All class members are initialized in the order they are declared in the class, so you could even have

struct foo
{
    int a;
    int b;
    int c;
    foo() : c(b + 1), b(a + 1), a(1) {}
};

and you would still be okay. If you had

struct foo
{
    int b;
    int c;
    int a;
    foo() : a(1), b(a + 1), c(b + 1) {}
};

on the other hand, both b and c would be initialized with an indeterminate value and using them would be undefined behavior.

Upvotes: 2

Brian Bi
Brian Bi

Reputation: 119089

As pointed out in the comments, non-static data members are initialized in declaration order. In order to prevent confusion, you should always write the member initializers in declaration order. In the case presented in the question, I will therefore assume that the order in which the members were declared is:

int m1_;
int m2_;
int* m3_;
int* m4_;

Assuming that is the case, the code is well-defined and does what you expect it to do. This is guaranteed by [intro.execution]/12.3, which guarantees that each member initialization is a full-expression, and [class.base.init]/13.3, which guarantees that these initializations occur in declaration order.

Upvotes: 2

Related Questions