为什么静态成员不能在类内初始化
(2014-12-29 21:00:51)
标签:
股票 |
分类: 汇编/C/CC |
-
class
Test { -
public:
-
static int a = 5; -
};
-
//
test.h -
class
Test { -
public:
-
static int a; -
};
-
//
farm1.cpp -
#include
"test.h" -
-
void
fun() { -
Test t; -
t.a = 3; -
}
就定义了一个局部对象,那么自然而然的,当这个函数执行完毕的时候,对象t析构,静态成员变量a的空间被释放掉。那就根本无法达到类共享静态成员变量的目的。所以有如下结论:静态成员变量在类实例化之前就已经存在了,并且分配了内存,它交由类专属使用(这是靠static的内部链接属性实现的),类无法控制它何时被分配内存,何时释放。我们不妨把它理解为一个在类中声明,专属于类的全局变量,它的链接属性为内部链接。
-
//
farm1.cpp -
-
class
Test { -
public:
-
static int a = 0; -
}
-
-
void
fun() { -
Test t; -
t.a = 3; -
}
这里面的静态成员变量不再是一个声明,而是定义,当函数fun执行到"t.a = 3;"时,不会再把a当成为一个外部符号,不会把它放入未解决符号表中。a首先被赋值为0,然后被修改为3。再看以下代码:
-
//
farm2.cpp -
#include
"test.h" -
-
void
fun() { -
Test t; -
t.a += 3; -
}
-
-
展开后:
-
//
farm2.cpp -
-
class
Test { -
public:
-
static int a = 0; -
};
-
-
void
fun() { -
Test t; -
t.a += 3; -
}
这里面是同样的道理,"static int a = 0;"不再是一个声明,而是定义,当函数fun执行到"t.a += 3;"时,不会把a当成一个外部符号,不会把它放入未解决符号表中。所以在本编译单元里寻找t.a,发现值为0,那么"t.a += 3;"的执行结果是t.a的值为3,而不是6,没有类的对象共享静态成员变量的目的。
-
//
test.h -
class
Test { -
public:
-
const static int a = 5; -
}
那是因为const使其成为了常量,不会担心上面所述的问题。但是,这样的定义,虽然值是不会改变,会不会造成无法共享静态成员变量a呢?因为在包含该类的头文件的cpp里面,将#include "test.h"扩展后,都有这么一句"const int a = 5;"这岂不是在不同的地方定义了静态成员变量a么?也就是说,当我们要取a的地址的时候,会不会发现在包含test.h的各个cpp中,取得a的地址不同?
-
#include
"test.h" -
-
void
Farm1::test() -
{
-
Test t; -
int b = t.a; -
}
该段代码经过反汇编后:
-
void
Farm2::test() -
{
-
00411410
push ebp -
00411411
mov ebp,esp -
00411413
sub esp,0E8h -
00411419
push ebx -
0041141A
push esi -
0041141B
push edi -
0041141C
push ecx -
0041141D
lea edi,[ebp-0E8h] -
00411423
mov ecx,3Ah -
00411428
mov eax,0CCCCCCCCh -
0041142D
rep stos dword ptr es:[edi] -
0041142F
pop ecx -
00411430
mov dword ptr [ebp-8],ecx -
Test t; -
int b = t.a; -
00411433
mov dword ptr [b],5 -
}
可以看到int b = t.a;的汇编语句是:
00411433
这说明编译器已经对const int static a = 5;优化了。注意:只有静态常量整形数据成员才可以立即初始化