S
Shriramana Sharma
Hello. I have been trying to understand how the initialization of data members of a class happens, esp. static members. I should note that I am using GCC 4.6.3 (64 bit) that came with Kubuntu Precise for my testing, so the error messages I inline in comments are from that. And all of the errors are compiler errors except for one which I have marked as a linker error.
I have inlined my queries in comments with three slashes: /// -- I would much appreciate clarifications to those queries. Thank you very much in advance!
struct a {
a () {}
// int i = 1 ;
// static int ii = 2 ;
// const int iii = 3 ;
/// Q: Why does ISO C++ forbid initialization within the class definition of all three above but not the below?
static const int iiii = 4 ;
} ;
struct b {
b () {}
int i ;
// int & ir = i ; // "i cannot appear in constant expr", "iso c++ forbids initialization of member"
// int * ip = &i ; // "i cannot appear in constant expr", "& cannot appear in constant expr"
/// Q: I get that without an object (together with its members) actually being created I can't produce a reference to it or take its address. (it = either object or member). But I don't get how this is a constant expr.
} ;
struct c {
c () : ir ( i ), ip ( &i ) {}
int & ir ; int * ip ; int i ;
/// Q: Given that I am declaring i after ir and ip, how is it that I can initialize ir and ip before i?
} ;
struct d {
d () /*: i ( 1 )*/ {} // "can only be initialized at definition"
/// Q: Why is this an error? I can do i=1 within the {} and it is not wrong, but it is wrong to do it before the {} ?
static int i ;
} ;
struct e {
e () {}
static const int i = 1 ;
static const double ii = 1.1 ;
// static const int * const ip = &i ; // "invalid in-class initialization of static member of non-integral type"
/// Q: I don't get it why I can't take address of static member in the class definition. Perhaps because the static object is only created after the entire definition is read? Why would that be so? And when I am able to initialize a static double, why does it say "non-integral type"?
} ;
struct f {
f () {}
static const int i = 1 ;
// const int * const ip = &i ; // "& cannot appear in constant expr", "iso c++ forbids initialization of member"
/// Q: Um, I guess I can't use & because as in struct e above, the member iis only actually created after reading the entire definition. But the error messages don't reflect that clearly. Why?
} ;
# ifdef TEST1
struct g {
static const int i = 5 ;
static const int * const ip ;
} ;
const int * const g::ip = &i ; // LINKER: undefined reference to 'g::i'
# endif
struct h {
static const int i ;
static const int * const ip ;
} ;
const int h::i = 0 ;
const int * const h::ip = &i ;
/// Q: I expect this class to be identical to the above, with the only exception being that I have initialized i at namespace scope. The above doesn'twork but this works? The standard (I'm reading the last public draft of C++11) seems to say at 9.4.2.3 that "the member shall still be defined in namespace scope if it is odr-used in the program". I wonder if this applies inthe present case. And I am unable to understand the lengthy definition of "odr-used" so I would appreciate a brief explanation if possible.
struct j {
static const int * const ip ;
} ;
const int * const j::ip = new int ;
# ifdef TEST2
struct k {
static const int * const ip = new int ; // "'new' cannot appear in a constant expr", "invalid in-class initialization of static member of non-integral type"
/// Q: Again, I'm not sure why this is a constant expr, why new can't appear in it, and why it says "non-integral" type.
} ;
# endif
int main () {
delete j::ip ;
# ifdef TEST2
delete k::ip ;
# endif
}
I have inlined my queries in comments with three slashes: /// -- I would much appreciate clarifications to those queries. Thank you very much in advance!
struct a {
a () {}
// int i = 1 ;
// static int ii = 2 ;
// const int iii = 3 ;
/// Q: Why does ISO C++ forbid initialization within the class definition of all three above but not the below?
static const int iiii = 4 ;
} ;
struct b {
b () {}
int i ;
// int & ir = i ; // "i cannot appear in constant expr", "iso c++ forbids initialization of member"
// int * ip = &i ; // "i cannot appear in constant expr", "& cannot appear in constant expr"
/// Q: I get that without an object (together with its members) actually being created I can't produce a reference to it or take its address. (it = either object or member). But I don't get how this is a constant expr.
} ;
struct c {
c () : ir ( i ), ip ( &i ) {}
int & ir ; int * ip ; int i ;
/// Q: Given that I am declaring i after ir and ip, how is it that I can initialize ir and ip before i?
} ;
struct d {
d () /*: i ( 1 )*/ {} // "can only be initialized at definition"
/// Q: Why is this an error? I can do i=1 within the {} and it is not wrong, but it is wrong to do it before the {} ?
static int i ;
} ;
struct e {
e () {}
static const int i = 1 ;
static const double ii = 1.1 ;
// static const int * const ip = &i ; // "invalid in-class initialization of static member of non-integral type"
/// Q: I don't get it why I can't take address of static member in the class definition. Perhaps because the static object is only created after the entire definition is read? Why would that be so? And when I am able to initialize a static double, why does it say "non-integral type"?
} ;
struct f {
f () {}
static const int i = 1 ;
// const int * const ip = &i ; // "& cannot appear in constant expr", "iso c++ forbids initialization of member"
/// Q: Um, I guess I can't use & because as in struct e above, the member iis only actually created after reading the entire definition. But the error messages don't reflect that clearly. Why?
} ;
# ifdef TEST1
struct g {
static const int i = 5 ;
static const int * const ip ;
} ;
const int * const g::ip = &i ; // LINKER: undefined reference to 'g::i'
# endif
struct h {
static const int i ;
static const int * const ip ;
} ;
const int h::i = 0 ;
const int * const h::ip = &i ;
/// Q: I expect this class to be identical to the above, with the only exception being that I have initialized i at namespace scope. The above doesn'twork but this works? The standard (I'm reading the last public draft of C++11) seems to say at 9.4.2.3 that "the member shall still be defined in namespace scope if it is odr-used in the program". I wonder if this applies inthe present case. And I am unable to understand the lengthy definition of "odr-used" so I would appreciate a brief explanation if possible.
struct j {
static const int * const ip ;
} ;
const int * const j::ip = new int ;
# ifdef TEST2
struct k {
static const int * const ip = new int ; // "'new' cannot appear in a constant expr", "invalid in-class initialization of static member of non-integral type"
/// Q: Again, I'm not sure why this is a constant expr, why new can't appear in it, and why it says "non-integral" type.
} ;
# endif
int main () {
delete j::ip ;
# ifdef TEST2
delete k::ip ;
# endif
}