Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`static`, `extern`, `const` in header file

Tags:

c++

//a.h

extern int x1;
static int x2;
int x3;
static const int x4;

class A {
    public:
        static const int x5 = 10;
};

a.h will be included by multiple .cpp files, my question is:

1.x1 is just a declaration, isn't it? So its definition should be done in one of those .cpp files, right?

2.x2 is a definition, right? I used to think that static int is also a declaration just like extern int, but I was wrong. x2 will only be visible in a.h?

3.x3 will be defined multiple times if a.h is included in multiple .cpp files, so x3 will result in compile-error, right?

4.x4 is a definition, right?

5.Here in class A, x5 is a declaration, yes. But what about x4?

like image 677
Alcott Avatar asked Mar 28 '12 13:03

Alcott


1 Answers

1.x1 is just a declaration, isn't it? So its definition should be done in one of those .cpp files, right?

Correct

2.x2 is a definition, right? I used to think that static int is also a declaration just like extern int, but I was wrong. x2 will only be visible in a.h?

A different x2 will be available in each translation unit that includes the header.

3.x3 will be defined multiple times if a.h is included in multiple .cpp files, so x3 will result in compile-error, right?

More precisely it will result in a linker error. The compiler processes each translation unit, the linker binds them together and detects that the symbol is defined multiple times.

4.x4 is a definition, right?

Yes, it is a definition, but as with x2 each translation unit will have it's own x4 (both because of static and because it is const which implies internal linkage

5.Here in class A, x5 is a declaration, yes. But what about x4?

Yes, x5 is a declaration only (with initialization). The confusion might arise because the keyword static is reused to mean different things in different contexts. In x5 it means attribute of the class, while in x4 it means internal linkage

This last case is special. It is the only declaration (IIRC) where the declaration can have a value, and the reason is that it allows the compiler to use the value of the constant in all translation units that include that header as a compile time constant. If the value had to be provided with the definition, then only a single translation unit would have access to that value. The definition of that static member would be:

const int A::x5; // no initialization here

And you must provide one if the member is odr-used. Now the fact is that in most cases the constant will not be odr-used as the compiler will substitute the value when the expression A::x5 is used. Only when the member is used as an lvalue you need the definition, for example:

void f( const int & ) {}
int main() {
   f( A::x5 );
}

Because the argument to f is a reference, the use of A::x5 requires an lvalue (note, const-ness and lvalue/rvalue-ness are almost orthogonal), and that requires the definition of the member in a single translation unit in your program.

like image 77
David Rodríguez - dribeas Avatar answered Oct 07 '22 00:10

David Rodríguez - dribeas