c++ - 静态与新建/Malloc

标签 c++ c static

我想知道人们是否可以对“静态”的使用有所了解。我从未遇到过明确声明变量或方法为静态的问题。我了解到,在将某些内容声明为“静态”时,它会塞入程序的数据段(类似于全局变量),因此可以在程序运行时访问该变量。如果是这种情况,为什么不只将静态变量设为全局变量。哎呀,为什么不使用新的或malloc将此变量扔到堆上呢,这两种方法都确保变量在整个程序运行期间都对您可用。

最佳答案

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

在文件作用域声明(我认为问题是关于什么)中,静态控制标识符的可见性。

让我们搁置C++并使用C概念。

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

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

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

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

有时,C程序甚至对通过全局指针全局引用的“单个”对象也使用malloc。这些对象的行为就像事实上的静态变量一样,因为它们的生存期几乎是整个程序的生存期,并且可以通过按名称访问的指针进行访问。如果对象具有直到运行时才知道的属性(例如大小),或者如果对象的初始化很昂贵并且并不总是需要它们(仅在程序中发生某些情况时),则此选项很有用。

关于staticextern的补充类事实:

  • 在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! */
       }
    }
    
  • 显然,单词“external”在“任何功能之外”和“程序范围内的链接”之间具有不明确的含义,这种歧义性体现在extern关键字中。
  • 在C++中,static具有其他含义。在类声明中,它声明“静态成员函数”,这些成员属于类范围,并且与非静态成员函数具有对类实例的相同访问权限,但不会在对象上调用(不具有隐式this参数)。标记为static的类数据成员具有单个类范围的实例;它们不是按对象实例化的。 (不幸的是,它们没有像真正的面向对象的类变量那样正确地参与继承,可以在派生类中将其重写为实例,反之亦然。)
  • 在C++中,可以使用未命名的namespace而不是static来实现类似于内部链接的隐私。命名空间使内部/外部链接概念在大多数情况下都不符合C兼容性。
  • C++以特殊的extern语法(例如extern "LANG")包含extern "C"
  • static_caststatic无关;它们的共同点是“静态”,意思是“在程序运行之前”:静态存储是在运行之前确定的,静态转换的转换也是在编译时确定的(没有运行时类型信息)。
  • 关于c++ - 静态与新建/Malloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21008297/

    相关文章:

    c++ - 在派生类的构造函数中初始化没有默认构造函数的基类

    c - 在我尝试用 C 编写的简单函数中出现 "unused variable"和 "undeclared identifier"错误,但我不明白为什么

    无法安装我的驱动程序

    c++ - 有没有一种方法可以机械地识别哪些操作对移出的对象是安全的?

    c++ - 写入文件的最后 32 个字符

    c++ - boost.asio 在单线程和多线程进程中的复合操作

    c++ - 在类成员声明中获取 sizeof(MyClass)

    C作业——编译代码时发现木马

    c++ - 使用参数初始化局部静态

    java - 从java中的另一个类访问静态变量