在C和C ++中,“const static”是什么意思?
const static int foo = 42;  我在StackOverflow的一些代码中看到了这一点,我无法弄清楚它在做什么。 然后我在其他论坛上看到一些混淆的答案。 我最好的猜测是它在C中用来隐藏其他模块的常量foo 。 它是否正确? 如果是这样,为什么任何人都可以在C ++上下文中使用它,你可以把它变成private ? 
它在C和C ++中都有使用。
 正如你猜测的那样, static部分将其范围限制在编译单元中 。 它也提供了静态初始化。  const只是告诉编译器不要让任何人修改它。 这个variables要么根据体系结构放在数据段中,要么放在内存中标记为只读。 
 所有这些都是C如何处理这些variables(或者C ++如何处理命名空间variables)。 在C ++中,标记为static的成员由给定类的所有实例共享。 无论是否私有都不会影响一个variables被多个实例共享的事实。 如果有任何代码会尝试修改,那么在那里有const会警告你。 
如果它是严格私有的,那么每个类的实例都会得到它自己的版本(优化器尽pipe)。
 很多人都给出了基本的答案,但没有人指出,在C ++中, const在namespace级别默认为static (有些给出了错误的信息)。 请参阅C ++ 98标准部分3.5.3。 
首先是一些背景:
翻译单元:预处理器(recursion)之后的源文件包括其所有包含文件。
静态链接:符号仅在其翻译单元中可用。
外部链接:其他翻译单元提供了一个符号。
 在namespace级别 
这包括全局名称空间又名全局variables 。
 static const int sci = 0; // sci is explicitly static const int ci = 1; // ci is implicitly static extern const int eci = 2; // eci is explicitly extern extern int ei = 3; // ei is explicitly extern int i = 4; // i is implicitly extern static int si = 5; // si is explicitly static 
在function级别
  static意味着函数调用之间的值保持不变。 
 函数staticvariables的语义类似于全局variables,因为它们驻留在程序的数据段 (而不是堆栈或堆)中,请参阅此问题以获取有关staticvariables生命周期的更多详细信息。 
 在class上 
  static意味着该值在类的所有实例之间共享,并且const意味着它不会改变。 
这行代码实际上可能出现在几个不同的上下文中,并且它们的行为大致相同,但有一些细微的差别。
命名空间范围
 // foo.h static const int i = 0; 
 包含标题的每个翻译单元中都会显示“ i ”。 但是,除非实际使用对象的地址(例如' &i '),否则我很确定编译器将“ i ”视为types安全0 。 如果再有两个翻译单元采用“ &i ”,则每个翻译单元的地址将会不同。 
 // foo.cc static const int i = 0; 
  ' i '有内部联系,所以不能从这个翻译单位以外引用。 但是,除非你使用地址,否则它很可能被视为types安全的0 。 
值得指出的一点是,下面的声明是:
 const int i1 = 0; 
 与static const int i = 0 完全一样。 用const声明的一个名字空间中的variables并没有用extern显式声明,而是隐含的静态的。 如果你想到这一点,C ++委员会的目的是允许在头文件中声明constvariables,而不需要static关键字来避免破坏ODR。 
class级范围
 class A { public: static const int i = 0; }; 
 在上面的例子中,标准明确规定如果地址不是必需的,“ i ”不需要定义。 换句话说,如果只使用' i '作为types安全的0,那么编译器将不会定义它。 类和名称空间版本之间的一个区别是“ i ”(如果在两个或更多的翻译单元中使用)的地址对于类成员将是相同的。 在使用地址的地方,你必须有一个定义: 
 // ah class A { public: static const int i = 0; }; // a.cc #include "ah" const int A::i; // Definition so that we can take the address 
这是一个小空间优化。
当你说
 const int foo = 42; 
你没有定义一个常量,而是创build一个只读variables。 编译器足够聪明,只要看到foo就可以使用它,但是它也会在初始化的数据区域中为它分配空间。 这样做是因为,如所定义的,foo具有外部链接。 另一个汇编单位可以这样说:
extern const int foo;
获取其价值。 这不是一个好的做法,因为编制单位不知道foo的价值是什么。 它只知道它是一个const int,只要使用它就必须从内存中重新加载值。
现在,声明它是静态的:
 static const int foo = 42; 
编译器可以进行通常的优化,但是也可以说“嘿,这个编译单元之外没有人能看到foo,我知道它总是42,所以不需要为它分配任何空间”。
我还应该注意,在C ++中,防止从当前编译单元转义名称的首选方法是使用匿名名称空间:
 namespace { const int foo = 42; // same as static definition above } 
它缺less一个'int'。 它应该是:
 const static int foo = 42; 
在C和C ++中,它声明一个整型常量,其值为42。
为什么42? 如果你还不知道(很难相信你不知道),那就是对生命的回应,宇宙和万物的回应 。
在C ++中,
 static const int foo = 42; 
是定义和使用常量的首选方法。 即使用这个而不是
 #define foo 42 
因为它不会颠覆型号安全系统。
这是全局常量只有在编译模块(.cpp文件)中才可见/可访问。 BTW使用静态为此目的已被弃用。 更好地使用匿名命名空间和枚举:
 namespace { enum { foo = 42 }; } 
所有的好的答案,我想添加一个小细节:
如果您编写插件(例如,由CAD系统加载的DLL或.so库),那么static就是一个避免名称冲突的生命保护程序,如下所示:
- CAD系统加载一个插件A,它有一个“const int foo = 42;” 在里面。
- 系统加载一个插件B,其中包含“const int foo = 23;” 在里面。
- 结果,插件B将为foo使用值42,因为插件加载器会意识到,已经有一个具有外部链接的“foo”。
更糟糕的是:根据编译器优化,插件加载机制等,第3步可能会有所不同。
我有两个插件中的两个辅助函数(相同的名称,不同的行为)曾经有过这个问题。 宣布他们静态解决了这个问题。
是的,它从其他模块隐藏了一个模块的variables。 在C ++中,当我不需要/需要更改一个会触发不必要的重build其他文件的.h文件时,我会使用它。 另外,我把静态的第一:
 static const int foo = 42; 
而且,根据它的用途,编译器甚至不会为它分配存储空间,只是“内联”它所使用的值。 如果没有静态的,编译器不能假定它没有在其他地方使用,也不能内联。
使其保持私密仍然意味着它出现在标题中。 我倾向于使用“最弱”的方式。 请参阅Scott Meyers的这篇经典文章: http : //www.ddj.com/cpp/184401197 (这是关于函数,但也可以在这里应用)。
根据C99 / GNU99规范:
- 
static- 
是存储类说明符 
- 
文件级作用域的对象默认具有外部连接 
- 具有静态说明符的文件级范围的对象具有内部链接
 
- 
- 
const- 
是types限定符(是types的一部分) 
- 
关键字应用到即时左侧实例 – 即 - 
MyObj const * myVar;– 不合格的指向const限定对象types的指针
- 
MyObj * const myVar;– const限定指向非限定对象types的指针
 
- 
- 
最左边的用法 – 应用于对象types,不可变 -  const MyObj * myVar;– 不合格的指向const限定对象types的指针
 
-  
 
- 
从而:
 static NSString * const myVar;  – 不变的指向内部连接的不可变string的指针。 
 缺lessstatic关键字将使全局variables名称可能导致应用程序中的名称冲突。