我想知道人们是否可以对"静态"的使用有所了解.我从来没有遇到过我明确声明变量或方法为静态的问题.我理解,当声明某些东西为"静态"时,它会被填充到程序的数据段中,类似于全局变量,因此变量可以在程序运行时访问.如果是这种情况,为什么不将静态变量设为全局变量.地狱,为什么不使用new或malloc将这个变量放在堆上,这两种方法都确保在整个程序运行期间变量可用.
static 在C中有多种含义,而C++则更多.
在文件范围声明中(我认为问题是关于),static控制标识符的可见性.
让我们留出C++并使用C概念.
名称对象或函数的文件范围标识符具有链接.链接可以是外部(程序范围)或内部(在一个翻译单元内).
static 指定内部链接.
这很重要,因为如果具有内部链接的名称出现在多个单元中,则这些出现不相关.一个模块可以具有静态foo功能,而另一个模块可以具有不同的foo功能.它们都存在,并且可以通过foo各自单位的名称到达.
外部链接是不可能的:必须有一个foo.
malloc创建一个可能在程序中随处可用的对象,只要它没有被释放,但在不同的意义上.如果有指针,则该对象可用.指针是一种"运行时名称":访问对象的访问键.如果您知道其名称(在编译时)以及该对象和函数是否具有相对于您尝试访问它的位置的正确类型的链接,则Linkage会使对象或函数可用.
在多个程序生效并终止的动态操作系统中,其静态数据和功能(无论它们是否具有外部或内部链接)的存储实际上是动态分配的.加载程序的系统例程必须做类似于malloc为程序的所有固定区域获取内存的操作.
有时C程序malloc甚至使用通过全局指针全局引用的"单例"对象.这些对象的行为类似于事实上的静态变量,因为它们的生命周期几乎与整个程序的生命周期相同,并且可以通过指针访问,而指针可以通过名称访问.如果对象具有直到运行时才知道的属性(例如大小),或者它们的初始化很昂贵且并不总是需要它们(仅在程序中出现某些情况时),这将非常有用.
关于static和的补充事实extern:
在C中,在文件范围内,extern确保省略初始化程序的对象的声明实际上是一个声明.没有extern它是一个暂定的定义,但如果存在初始化器,那么它就是一个定义.
在C中,文件范围extern并不意味着"此声明具有外部链接",令人惊讶.一个extern声明自同名的先前声明继承联动.
C中的块范围extern意味着"此名称引入此范围,引用具有外部链接的外部定义".链接继承自名称的先前文件范围声明(如果存在),否则它是外部的.
static对象上的块范围控制不是链接,而是存储持续时间.甲static对象在进入块中的每个时间实例化不; 它的单个副本存在,可以在程序启动之前初始化.(在C++中,非常量表达式可以初始化此类对象或其成员;在这种情况下,初始化在块的第一次执行时发生).
块范围static函数声明声明具有内部链接的函数.
在块作用域中,无法声明具有内部链接的外部对象名称.矛盾的是,extern以下代码段中的第一个声明是正确的,但第二个,块范围的声明是错误的!
static int name; /* external name with internal linkage */
extern int name; /* redundant redeclaration of the above */
void foo(void)
{
int name; /* local variable shadowing external one */
{
/* attempt to "punch through" shadow and reach external: */
extern int name; /* ERROR! */
}
}
Run Code Online (Sandbox Code Playgroud)显然,"外部"一词在"任何功能之外"和"程序范围之间的联系"之间具有模糊含义,并且这种模糊性被卷入extern关键字.
在C++中,static具有其他含义.在类声明中,它声明属于类作用域的"静态成员函数",并且与非静态成员函数具有相同的类实例访问权限,但不在对象上调用(不具有隐式this参数).标记的类数据成员static具有单个类范围的实例; 它们不是针对每个对象实例化的.(不幸的是,它们没有像真正的面向对象的类变量那样正确地参与继承,它们可以在派生类中被覆盖为实例,反之亦然.)
在C++中,类似于内部链接的隐私可以使用未命名namespace而不是static.命名空间使内部/外部链接概念主要成为C兼容性的过时机制.
C++涉及extern特殊extern "LANG"语法(例如extern "C").
static_cast与...无关static; 它们的共同点是"静态"意味着"在程序运行时之前":静态存储在运行时确定,静态转换的转换也在编译时确定(没有运行时类型信息).
| 归档时间: |
|
| 查看次数: |
1254 次 |
| 最近记录: |