C++静态变量

flmtquvp  于 2022-12-24  发布在  其他
关注(0)|答案(3)|浏览(198)

我想知道头文件中的静态变量和类中声明的静态变量有什么区别。当静态变量在头文件中声明时,它的作用域是限制在.h文件中还是跨越所有单元。通常静态变量在类中声明时,是在.cpp文件中初始化的,对吗?所以这是否意味着静态变量的作用域限制在2个编译单元?

mklgxw1f

mklgxw1f1#

请原谅我回答你的问题时没有按顺序,这样更容易理解。
在头文件中声明静态变量时,其范围限于. h文件或所有单元。
没有"头文件作用域"这样的东西。头文件被"包含"到源文件中。翻译单元是"包含"头文件中的文本的源文件。无论你在头文件中写入什么,都会"复制"到每个包含的源文件中。
因此,在头文件中声明的静态变量类似于每个源文件中的静态变量。
因为用这种方式声明变量static意味着内部链接,所以头文件中的每个翻译单元#include都有自己的**,独立的变量(在翻译单元之外不可见),这通常不是你想要的。
我想知道头文件中的静态变量和类中声明的静态变量有什么区别。
在类声明中,static意味着类的所有示例 * 共享 * 这个成员变量;也就是说,你可能有数百个这种类型的对象,但是当这些对象中的一个引用static(或"class")变量时,所有对象的值都是相同的,你可以把它看作是一个"class global"。
通常静态变量在类中声明时也会在. cpp文件中初始化,对吗?
是的,* 一个 *(并且只有 * 一个 *)翻译单元必须初始化类变量。
那么这是否意味着静态变量的作用域被限制为2个编译单元呢?
正如我所说:

  • 标头不是编译单元,
  • static根据上下文有完全不同的含义。

全局static将作用域限制为翻译单元。类static表示对所有示例全局。

    • PS:**检查Chubsdad答案的最后一段,关于在C++中不应该使用static来指示内部链接,而应该使用匿名名称空间(因为他是对的)。- ))
fdbelqdn

fdbelqdn2#

头文件中的静态变量:

假设'common.h'具有

static int zzz;

此变量'zzz'具有内部链接(此变量不能在其他翻译单元中访问)。包含'common.h'的每个翻译单元都有其自己的唯一对象,名称为'zzz'

类中的静态变量:

类中的静态变量不是类的子对象的一部分。静态数据成员只有一个副本,由类的所有对象共享。
$9.4.2/6 -“命名空间范围内类的静态数据成员具有外部链接(3.5)。局部类不应具有静态数据成员。”
假设'myclass.h'

struct myclass{
   static int zzz;        // this is only a declaration
};

并且myclass.cpp具有

#include "myclass.h"

int myclass::zzz = 0           // this is a definition, 
                               // should be done once and only once

并且"hisclass.cpp"具有

#include "myclass.h"

void f(){myclass::zzz = 2;}    // myclass::zzz is always the same in any 
                               // translation unit

并且"ourclass.cpp"具有

#include "myclass.h"
void g(){myclass::zzz = 2;}    // myclass::zzz is always the same in any 
                               // translation unit

因此,类静态成员并不局限于两个翻译单元,它们只需要在任何一个翻译单元中定义一次。
注意:不推荐使用“static”来声明文件范围变量,未命名的命名空间是上级的替代方法

n8ghc7c1

n8ghc7c13#

在类外部的头文件中声明的静态变量在包含该头文件的每个.c文件中将为file-scoped。这意味着在包含该头文件的每个.c文件中可以访问同名变量的单独副本。
另一方面,静态类变量是class-scoped,并且相同的静态变量可用于每个编译单元,该编译单元包括含有具有静态变量的类的头部。

相关问题