0

What I know:

From a post: C++: Initialization Order of Class Data Members

nonstatic data members shall be initialized in the order they were declared in the class definition

From C++ Primer :

Class definitions are processed in two phases:
• First, the member declarations are compiled.
• Function bodies are compiled only after the entire class has been seen.


Why can I initialize c before initializing b?

Btw, are the data member inside class declarations or definitions? I think they are definitions, but the quoted text above seems to indicate they are merely declarations.

Sample code, compiles well:

#include <iostream>
using namespace std;

struct Bar {
void funcA() const {
    c++;
}
int &c = b;
int b = 3;
};

int main()
{
    Bar b;
    b.funcA();
    cout << b.b << endl; 
}
Rick
  • 7,007
  • 2
  • 49
  • 79
  • 1
    Why not? Where do you see the problem here? Why do you care which one is initialized first in this case? It is possible to run into problems with order of initialization, but not in your example. – AnT stands with Russia Jul 19 '18 at 15:15
  • Looks like `c` is initialized to me, its a reference to `b`, and `b` is initialized as well. Could also initialize `b` through `c` since for all intents and purposes they refer to the same data. – Havenard Jul 19 '18 at 15:16
  • @AnT Because you can't do this outside a class.`int &c = b; int b = 3;` – Rick Jul 19 '18 at 15:17
  • @Havenard The point is that `c` is constructed before `b` is, so questions whether this is valid do arise. – Baum mit Augen Jul 19 '18 at 15:19
  • @Rick: Well, in that case the question is: why can you use `b` in `c`'s initializer, seemingly before `c` is declared. It has nothing to do with when `b` is initialized. And the answer is: C++11 in-class member initializers is a very peculiar feature. They are very different from "ordinary" initializers. In-class initializers are just "blueprints" that will be used later for generating class *constructors*. Constructors are member functions , they can see the whole class. – AnT stands with Russia Jul 19 '18 at 15:21
  • @Rick yes you can – Slava Jul 19 '18 at 15:21
  • @Rick I appreciate that it's not *exactly* the same question, so we could reopen if you disagree. It's the same thing at its core, though. – Baum mit Augen Jul 19 '18 at 15:21
  • I think the problem is that when `b` and `c` are not class members, instructions are resolved sequentially and semantics such as `b` does not exist when `c` is declared will matter. Making them class members should workaround this limitation since they are not declared individually but as part of a class. – Havenard Jul 19 '18 at 15:21
  • @BaummitAugen ya, allow me to read the duplicated one you marked first. – Rick Jul 19 '18 at 15:21
  • 1
    @Havenard does not matter, consider this `extern int i; int &ri = i; int i;` in namespace context. The same thing. – Slava Jul 19 '18 at 15:25
  • 1
    @Slava Yes, I know this one. But let's first put this situation aside.. Actually you give a declaration first for `i`. If I remember correctly, the way to declare buit-in type is using `extern`. – Rick Jul 19 '18 at 15:26
  • 2
    @Rick why to put it aside? This is the same situation exactly. If compiler knows there is a var you can create a reference to it, does not matter if it is initialized or not yet, does not matter if it is member variable or global one. It does not work with local vars just because name of local variable is not available if it is declared after reference. – Slava Jul 19 '18 at 15:29
  • Makes sense to me. – Havenard Jul 19 '18 at 15:29
  • @AnT Thank you. I was also thinking that the **in-class initializers** are just syntax sugar. But even constructor can see the whole class, doesn't `c` need to see `b` first? – Rick Jul 19 '18 at 15:29
  • @Slava that seems make sense. Give me a few mins.. – Rick Jul 19 '18 at 15:32
  • @Rick Just think about it this way, the structure of your whole class is implicitly declared before anything is implemented. If you had to manually declare before implementing, there would be a lot of redundant code. Besides you can't really manipulate an object before knowing it's structure beforehand so implementing it with partial knowledge of it's structure makes no sense, the compiler has to do it this way. – Havenard Jul 19 '18 at 15:37
  • @Havenard Yes, I got it. He's right. – Rick Jul 19 '18 at 15:40
  • @Slava Thanks . You're right. May I confirm one more thing? So those data members inside class are merely **declarations**, not definitions? Is this right? – Rick Jul 19 '18 at 15:42
  • Thinking of this question I came to this code https://stackoverflow.com/questions/51426859/c-reference-to-nowhere?noredirect=1#comment89824819_51426859 it seems funny, but folks do not seem to like it. – Slava Jul 19 '18 at 15:45
  • @Rick The short answer would be: the language specification says that in-class member initializers can "see" the whole class. So, despite being declared in that order, `c` can see `b` because language standard says so. – AnT stands with Russia Jul 19 '18 at 15:46
  • @AnT . I see. one more question... Is it right to think of data members inside class are merely declarations not definitions? – Rick Jul 19 '18 at 15:49
  • Much appreciate all your help. SO is awesome :D. – Rick Jul 19 '18 at 15:50
  • This code `int &ri = ri;` seems to be nonsense but actually may help to understand why such initialization is fine (mentioned in current question) and what happens there. – Slava Jul 19 '18 at 16:01

0 Answers0