静态与新/ Malloc

时间:2014-01-08 22:54:08

标签: c++ c static

我想知道人们是否可以对“静态”的使用有所了解。我从来没有遇到过我明确声明变量或方法为静态的问题。我理解,当声明某些东西为“静态”时,它会被填充到程序的数据段中,类似于全局变量,因此变量可以在程序运行时访问。如果是这种情况,为什么不将静态变量设为全局变量。地狱,为什么不使用new或malloc将这个变量放在堆上,这两种方法都确保在整个程序运行期间变量可用。

1 个答案:

答案 0 :(得分:8)

static在C中有多重含义,而C ++则更多。

在文件范围声明中(我认为问题是关于),static控制标识符的可见性。

让我们留出C ++并使用C概念。

名称对象或函数的文件范围标识符具有链接。链接可以是外部(程序范围)或内部(在一个翻译单元内)。

static指定内部链接。

这很重要,因为如果具有内部链接的名称出现在多个单元中,则这些出现不相关。一个模块可以具有静态foo功能,而同一程序中的另一个模块可以具有不同的foo功能。它们都存在,并且可以通过名称foo从各自的单位到达。

外部链接无法做到这一点:必须有一个foo

malloc创建一个可能在程序中随处可用的对象,只要它没有被释放,但在不同的意义上。如果有指针,则该对象可用。指针是一种"运行时名称":访问该对象的访问键。如果您知道其名称(在编译时),并且该对象和函数相对于您尝试访问它的位置具有正确的链接类型,则Linkage会使对象或函数可用。

在一个动态操作系统中,多个程序生效并终止,其静态数据和函数(无论它们是否具有外部或内部链接)的存储实际上是动态分配的。加载程序的系统例程必须执行与malloc类似的操作,以获取程序的所有固定区域的内存。

有时C程序使用malloc即使对于" singleton"通过全局指针全局引用的对象。这些对象的行为类似于事实上的静态变量,因为它们的生命周期几乎与整个程序的生命周期相同,并且可以通过指针访问,该指针可以通过名称访问。如果对象具有直到运行时才知道的属性(例如大小),或者它们的初始化很昂贵并且并不总是需要它们(仅在程序中出现某些情况时),这将非常有用。


关于staticextern的补充事实:

  • 在C中,在文件范围内,extern确保省略初始化程序的对象声明实际上是一个声明。没有extern它是一个暂定的定义,但是如果存在初始化器,那么它就是一个定义。

  • 在C中,文件范围extern并不意味着"这个声明有令人惊讶的外部链接" extern声明继承了先前同名声明的链接。

  • C中的块范围extern表示"此名称引入此范围,引用外部定义与外部链接&# 34 ;.该链接继承自名称的先前文件范围声明(如果存在),否则它是外部的。

  • 对象上的块范围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! */
       }
    }
    
  • 显然,"外部"在任何功能之外都有一个模糊的含义"和"程序范围的联系"这种歧义卷入了extern关键字。

  • 在C ++中,static具有其他含义。在类声明中,它声明了静态成员函数"属于类范围并且与非静态成员函数具有相同的类实例访问权限,但不在对象上调用(没有隐式this参数)。标记为static的类数据成员具有单个类范围的实例;它们不是针对每个对象实例化的。 (不幸的是,他们没有像真正的面向对象的类变量那样正确地参与继承,可以在派生类中重写为实例,反之亦然。)

  • 在C ++中,使用未命名的namespace而不是static可以实现类似于内部链接的隐私。命名空间使内部/外部链接概念主要成为C兼容性的过时机制。

  • C ++在特殊extern语法中涉及extern "LANG"(例如extern "C")。

  • static_caststatic无关;他们的共同点是"静态"意思是"在程序运行时之前":静态存储是在运行时之前确定的,静态强制转换的转换也是在编译时确定的(没有运行时类型信息)。