静态与新/Moloc

Static vs New/Malloc

本文关键字:Moloc 静态      更新时间:2023-10-16

我想知道人们是否可以了解"static"的用法。我从未遇到过明确声明变量或方法为static的问题。我知道,当将某个东西声明为"静态"时,它会被填充到程序的数据段中,类似于全局变量,因此该变量可以用于程序的运行。如果是这样的话,为什么不把一个静态变量变成全局变量呢。见鬼,为什么不使用一个新的或malloc将这个变量扔到堆上呢?这两种方法都可以确保在程序的整个运行过程中都可以使用这个变量。

static在C中有多种含义,C++甚至有更多含义。

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

让我们把C++放在一边,使用C的概念。

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

static指定内部链接。

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

这在外部链接中是不可能的:必须有一个foo

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

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

有时C程序甚至对通过全局指针全局引用的"singleton"对象使用malloc。这些对象的行为类似于事实上的静态变量,因为它们的生存期基本上相当于整个程序的生存期,并且是通过指针访问的,指针是按名称访问的。如果对象具有直到运行时才知道的属性(如大小),或者如果它们的初始化成本很高并且并不总是需要它们(仅当程序中出现某些情况时),则此选项非常有用。


关于staticextern的补充事实:

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

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

  • C中的块作用域extern的意思是"引入该作用域的名称是指具有外部链接的外部定义"。链接是从名称的上一个文件作用域声明继承的(如果存在),否则是外部的。

  • 对象上的块作用域static控制的不是链接,而是存储持续时间。CCD_ 18对象在每次进入块时不被实例化;存在它的单个副本,并且可以在程序启动之前进行初始化。(在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! */
    }
    }
    
  • 显然,"外部"一词在"任何功能之外"answers"程序范围内的链接"之间有着模糊的含义,这种模糊性与extern关键字有关。

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

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

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

  • CCD_ 30与CCD_;它们的共同点是"static",意思是"在程序运行时之前":静态存储在运行时之前确定,静态类型转换也在编译时确定(没有运行时类型信息)。