C++的static和extern关键字的说明
1. static关键字修饰的变量的生命周期的说明
#include <iostream>
void incrementAndPrint()
{
static int s_value = 1; // static duration via static keyword. This line is only executed once.
++s_value;
std::cout << s_value << std::endl;
} // s_value is not destroyed here, but becomes inaccessible
int main()
{
incrementAndPrint();
incrementAndPrint();
incrementAndPrint();
}
打印的结果是2 3 4 。因为s_value被声明为static的,它只会被创建和初始化一次。当它出了作用域范围后,仍然不会被销毁。
2. 通过static和extern关键字指定内部连接属性和外部链接属性
变量除了作用域和生命周期外,还有第三个属性,那就是linkage,即链接属性。变量的链接属性确定了标识符的多个实例是否指向相同的变量。
没有链接属性的变量只能从其存在的有限范围中引用。正常的局部变量就是没有链接属性的变量的例子。具有相同名称但在不同函数中定义的两个局部变量没有链接的,每个都将被视为一个独立变量。
internal variable:具有内部连接的变量称为内部变量(或静态变量),具有内部链接的变量可以在其定义的文件中的任何位置使用,但不能在其存在的文件外引用,即只能在该文件里面使用,不能被其他文件使用。
external variable:具有外部连接的变量称为外部变量。具有外部链接的变量可以在其定义的文件中以及其他文件中使用。
比如:
static int g_x; // g_x is static, and can only be used within this file。static修饰的全局变量,是内部变量,只能该文件里面使用
int main()
{
return 0;
}
extern double g_y(9.8); // g_y is external, and can be used by other files。extern修饰的全局变量,是外部变量,可以被该文件和其他文件同时使用
// Note: those other files will need to use a forward declaration to access this external variable //不过,其他文件使用该变量之前需要前置声明。
int main()
{
return 0;
}
注意:默认情况下,声明在块外(全局)的非const变量被假定为外部,要变为内部的,加static。声明在块外(全局)的const变量是内部的,要变为外部的,加extern。
3. 使用extern关键字做前置声明
int g_x; // external linkage by default。non-const globals have external linkage by default (global.cpp)
extern int g_y(2); // external linkage by default, so this extern is redundant and ignored
// in this file, g_x and g_y can be used anywhere beyond this point
extern int g_x; //前置声明g_x, forward declaration for g_x (defined in global.cpp) -- g_x can now be used beyond this point in this file (main.cpp)
int main()
{
extern int g_y; //前置声明g_y, forward declaration for g_y (defined in global.cpp) -- g_y can be used beyond this point in main() only
g_x = 5;
std::cout << g_y; // should print 2
return 0;
}
4. 方法的链接属性
函数具有与变量相同的链接属性。函数始终默认为外部链接,但可以通过static关键字设置为内部链接。
// This function is declared as static, and can now be used only within this file
// Attempts to access it via a function prototype will fail
static int add(int x, int y)
{
return x + y;
}