《C++ Primer》中指出,const对象仅在文件内有效(2.4章 page54)。

WHAT?

  const对象 :分两步 - 1,找到对象 2,加const (注意陷阱)

即没有#include!

1 const int i = 10;    //    ok
2 const char* s1 = "Do not use include"; // error! is not const-object
3 char* const s2 = "Do not use include"; // ok

HOW?

  通过对全局变量加上const限定符,限制变量的作用域为文件内(内部链接)。

  即:const对象的默认链接属性是内部链接;非const对象及函数的默认链接属性是外部链接

  类似这里的花括号

1 int main(int argc, char* argv[])
 2 {
 3     //花括号的存在使得代码合法
 4     { 
 5         int i = 1;
 6     }
 7     {
 8         int i = 2;
 9     }
10 }

WHY?

  当以初始化方式定义一个全局const变量时,如 const int i = 1,编译器会在编译阶段以数字替换变量。当多个文件中都有相同全局const变量时,由于变量不允许定义多次,而不能通过编译 。所以const限定符同时限定了变量的作用域,那么就相当于各个文件在自己的作用域内定义了独立的变量 - 即非共享的。

//const使得项目内三个不同的文件定义相同的变量变得合法
char* const s2 = "Do not use include"; // ok file a.cpp
char* const s2 = "Do not use include"; // ok file b.cpp
char* const s2 = "Do not use include"; // ok file c.cpp

extern

  如果各个文件需要共享同一个const对象,即在一处定义,多处使用。那么在定义和声明的地方都加上extern即可。

  PS. 非const对象不需要在定义前加上extern,然而加上也没错。

//在文件 a.cpp中定义
extern const int i = 10;    
extern char* const s2 = "Do not use include";
//在文件 b.cpp中声明
extern const int i;    
extern char* const s2;

include

  预处理器在处理#include指令时,会以指定文件的内容替代#include。所以如果一个文件如果需要被多个文件include时,最好不要有全局变量的定义,否则会因为多次定义变量而编译失败。

应用

  const限定文件作用域的方式,可以通过定义不同命变量替代。

  extern共享全局变量的方式,可以通过include声明文件代替(功能不尽相同,根据场景)

extern/static

最后,看下extern/static在C/C++中的意义

conftest文件是只能有一个函数吗_全局变量

外部链接:符号在整个程序范围内可见,在链接过程中,根据声明找到符号的定义。因此不可重复定义。 - 找不到定义,链接错误

内部链接:符号在单个编译单元(文件)内可见,链接时,只能在自己的编译单元寻找定义。因此在不同文件可以重复定义。 - 找不到定义,编译错误