1

This code does't compile, and the error information is "undefined reference to `A::a'":

code 1:

#include <iostream>
using namespace std;

class A
{
public:
    static const int a=0;
};

int main()
{
    cout<<&A::a<<endl;
    return 0;
}

But for a non-const static member it compiles:

code 2:

#include <iostream>
using namespace std;

class A
{
public:
    static int a;
};
int A::a=0;

int main()
{
    cout<<&A::a<<endl;
    return 0;
}

Is there just no way of accessing the address of a static const member of a class? If there is, how? And why code 1 does not compile?

Felix
  • 209
  • 1
  • 3
  • 8

3 Answers3

11

Put

const int A::a;

In the source file, otherwise the compiler doesn't generate an address for a. Note the value is not repeated here.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • What compiler are you using? – doctorlove Aug 07 '13 at 15:29
  • 4
    For integers, you can put the value in the header file(/class definition). This allows the value to be used directly by the compiler for optimizations and array sizes in other source files. But it is the line in the source file that actually assigns an address. This is because there is only one instance of a class static in memory across the whole project, so it can only appear in one translation unit. Without out it, the value never actually exists as a real object in memory. The value is just "copied and pasted" by the compiler where it is called and then forgotten. – Neil Kirk Aug 07 '13 at 15:33
8

This code does't compile

The code does not link, it does compile. The static const member requires a definition if its address is to be used, so just add a definition similar to the second code snippet:

const int A::a;

Taking the address of A::a means A::a is odr-used, and from section 9.4.2 Static data members of the C++11 standard (draft n3337), clause 3:

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

hmjd
  • 120,187
  • 20
  • 207
  • 252
1

Since you want to take the address, you still need to define the static member, as you do for the non-const version where you say

int A::a;

For the const version you also need

const int A::a;

See here for a good discussion - headline quote "compile-time constants don't have addresses."

Community
  • 1
  • 1
doctorlove
  • 18,872
  • 2
  • 46
  • 62