C++静态成员变量的定义与初始化注意事项

静态(statis)变量只在第一次被调用时声明并初始化,此后保存在堆上。而对于类的静态成员来说,同样是所有类共享一个静态成员,需要注意的是静态成员的初始化

如下面代码

class A
{
    public:
    static int a;
    // static int a = 1;  // ERROR
};
int A::a = 1;
int main()
{
    cout << A::a << endl;
}

这样是合法的,但如果直接在类内声明的同时初始化a,则会报错。

这样的原因Bjarne有解释过:

A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.

意思是,一般类的声明是放在头文件中,而这个头文件可能被include到很多地方。为了避免复杂链接导致的bug,C++要求每个对象(个人认为此处的object不局限于类对象,还包括int这些)都有唯一的定义,不然编译器不知道该把这个对象放在哪个内存地址。如果在A里面初始化静态成员,那么实例化每个类A的对象时都相当于定义了一次这个静态成员,这就违反了上述规则。

但这个规定有个例外,就是静态常量成员,如果我们写成下述形式

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

这就是没问题的,这是因为编译器知道静态常量成员的值不会变,因此会在编译阶段优化掉,比如将所有a出现的地方都替换成1之类的。这样使得a不会***store in memory***,从而没有违反上述规则。

但这也有需要注意的地方,如果我们执行下面的代码

class A
{
    public:
    static const int a = 1; 
    static const int b; 
};
const int A::b = 2;
int main()
{
    cout<< &A::a << endl;	// ERROR: undefined reference to "A::a"
    cout<< &A::b << endl;
    return 0;
}

在外部对静态常量成员b取地址,编译没问题,但对a取地址则报错说找不到这个成员,这进一步说明成员a被优化掉了。

另外在上述代码我们可以发现,如果是在类外初始化静态成员,则不用再加static,因为一般语义下的static是C语言中的**“静态””静态成员“**这一语义是C++独有的且只在类内部生效

class A
{
    public:
    static int a; 
};
int A::a = 1;        // 正确
static int A::a = 1; // confusing and illegal, is it static LINKAGE
                     // or static STORAGE DURATION
                     // or static MEMBERSHIP?

你可能感兴趣的:(C与CPP)