[C++]static详细说明

static用于声明全局变量(包括类的对象),局部变量全局函数,类的成员变量成员函数。即,static不能用于类、结构、枚举、联合的声明。

static有如下用途:

①使变量具有初值

静态变量具有初值。局部变量是没有初值,而static的局部变量将有初值。全局变量本身就具有初始值,所以static不发生作用。static用于全局变量,更多是用于解决命名冲突问题。

static确定初始值
#include <iostream>

void PrintNormal()
{
    int i;
    double d;
    char c;
    int* p;
    std::cout << a << std::endl;
    std::cout << i << std::endl;    // output: -858993460
    std::cout << d << std::endl;    // output: -9.25596e+061
    std::cout << c << std::endl;    // output: (乱码)
    std::cout << p << std::endl;    // output: CCCCCCCC
}

void PrintStatic()
{
    static int i;
    static double d;
    static char c;
    static int* p;
    std::cout << a << std::endl;
    std::cout << i << std::endl;    // output: 0
    std::cout << d << std::endl;    // output: 0
    std::cout << c << std::endl;    // output: (空)
    std::cout << p << std::endl;    // output: 00000000
}

int main()
{
    PrintNormal();
    PrintStatic();
    system("pause");
}

 

②声明全局变量

如果一个变量在所有的块之外,那么这个变量是全局变量,具有static duration(即也有初始值)和external linkage特性。注意要使用extern关键字。如果两个编译单元都使用同名的全局变量,将报错。(Visual Studio中。Linux下参考强符号、弱符号)

声明全局变量
// external linkage
int a;
另一个文件使用之
#include <iostream>
extern int a;
int main()
{
    std::cout << a << std::endl;
    system("pause");
}

但是,用static修饰后,此变量将变为external linkage。无法被外部Link。

声明全局静态变量
// external linkage
static int a = 5;
另一个文件中使用将报错,可以声明同名的变量
#include <iostream>
static int a;
// 将报错error LNK2001: 无法解析的外部符号 "int a" (?a@@3HA)
//extern int a;
int main()
{
    std::cout << a << std::endl;
    system("pause");
}

然而,static不支持类、结构、枚举的修饰,比起static修饰,更推荐使用namespace解决命名冲突(参见匿名namespace)。

③声明全局函数

全局函数类似,如果要改变其external linkage的特性,需要使用static。

④声明局部变量

用static声明局部变量虽然不改变其可见性,但变量仍然是static duration的,在其可见域外,仍可以使用地址访问之。

声明局部变量
#include <iostream>
int* p;
void foo()
{
    static int a;
    if (a == 0)
    {
        a = 10;
        p = &a;
    }
    a++;
}
void main()
{
    foo();
    // 将报错,a不可见
    //std::cout << a << std::endl;
    std::cout << *p << std::endl; // 11
    *p = 20;
    foo();
    std::cout << *p << std::endl; // 21
    system("pause");
}

 

⑤声明类的成员变量

除了显然意见的作用外,有两个注意点:

1. static的成员变量必须在file scope定义(即便不改变初值也要声明)

出错举例
#include <iostream>
class A
{
public:
    static int a;
};
// 如果不定义,会报错
/* error LNK2001: 无法解析的外部符号 "public: static int A::a" (?a@A@@2HA) */

// 如果在定义时增加了static关键字,会报错
/* error C2720: “A::a”: 成员上的“static ”存储类说明符非法 */
//static int A::a;

// 定义的时候可以指定初值
int A::a = 5;

void main()
{
    std::cout << A::a << std::endl;
    system("pause");
}

2. 对于const static类型,除了以上方法外,还可以直接在类中初始化~不是const不成哦~

const static
#include <iostream>
class A
{
public:
    static const int a = 5;
};
// 如果类中初始化了,这里就不能再次初始化了
//const int A::a = 5;

void main()
{
    std::cout << A::a << std::endl;
    system("pause");
}


⑥声明类的成员函数

显而易见的作用

 

附录:

union的成员是特殊的。不能将其成员定义为static。原因?看看union是干什么的吧~

这些英文术语极其难翻译,干脆直接贴上来。后边有解释。

static duration:静态生存期,程序创建时即分配此变量的内存,存放在全局静态存储区。程序创建时分配,结束时销毁。具有初始值。

C++内存分配:静态存储区常量存储区自由存储区

全局静态存储区:程序创建时分配,结束时销毁。

常量存储区:不允许修改。程序创建时分配,结束时销毁。

:局部变量、函数参数等。生存期结束后销毁。空间较小,不过可以手动修改。

:动态内存分配(new)。编译器不负责回收。

自由存储区:动态内存分配(malloc)。编译器不负责回收。

external linkage:可以外部链接的。即其他编译单元(.cpp文件)可以使用此变量。也就是说,如果在两个编译单元中使用了同名的static变量,会出错~

internal linkage:不能外部链接。

posted @ 2012-04-09 11:28  斯啦丝拉  阅读(2518)  评论(0编辑  收藏  举报