为什么在C ++中而不是在C中允许使用const全局变量的多个定义?

由于One Definition Rule,C或C ++中不允许对全局变量进行多重定义。 但是,在C ++中,const全局变量可以在多个编译单元中定义而没有错误。 这跟C中的不一样。

为什么C ++允许这样做而C不允许? 与C相比,为什么const全局的使用和行为在C ++中以这种方式与非const全局不同? C ++和C关于const的内容正在发生什么?

例如,这在C ++中是允许的,但在C中是错误的:

// Foo.cpp const int Foo = 99; // Main.cpp const int Foo = 99; int main() { cout << Foo << endl; return 0; } 

这对C来说很好,但C ++有问题:

 // Foo.cpp const int Foo = 99; // Main.cpp extern const int Foo; int main() { cout << Foo << endl; return 0; } 

 // Foo.cpp const int Foo = 99; // Main.cpp const int Foo = 99; 

命名空间范围内的 const变量具有内部链接。 所以它们基本上是两个不同的变量。 没有重新定义。

来自@ David的评论,3.5 / 3 [basic.link]:

具有命名空间范围(3.3.5)的名称具有内部链接(如果它的名称)
– 明确声明为静态的对象,引用,函数或函数模板,或
显式声明为const的对象或引用, 既未显式声明为extern,也未声明为具有外部链接 ; 要么
– 匿名联盟的数据成员。


在第二种情况下,你应该这样做(正确的方式):

 //Foo.h extern const int Foo; //use extern here to make it have external linkage! // Foo.cpp #include "Foo.h" const int Foo = 99; //actual definition goes here // Main.cpp #include "Foo.h" int main() { cout << Foo << endl; } 

我认为你要求的理由而不是具体的语言规则。

这样做的理由是它使const变量更容易使用。 它为#define一个常见用途提供了类型替换。

您可以使用const int max_count = 211;而不是#define MAX_COUNT 211 const int max_count = 211; 以完全相同的方式,例如共享头文件,而不必担心放置一个定义的位置。

您不能合法地更改const对象的值,因此在一个对象和具有相同值的多个对象之间没有明显的区别。

由于您可以在头文件中定义const对象,因此编译器可以直接在编译阶段使用该值,而不必将此类优化延迟到链接时修复。

基本上,在C ++中,const,非局部变量是真正的常量表达式,或constexpr。 这允许很多东西,比如TMP。

 const int five = 5; int main() { int x[five]; std::array arr; } 

在C中,它们只是一个无法修改的变量。 那是,

 const int five = 5; int main() { int x[five]; // Technically, this is a variable length array } 

相当于

 int five = 5; int main() { int x[five]; } 

实际上,C ++将某些const变量提升为新类别constexpr ,而在C中,这不存在,它们只是碰巧不可修改的变量。

看起来const 实际上并不生成外部符号 。

为什么英国人拼写COLOR,而美国人拼写COLOR?

它们是来自同一基础的两种不同语言,但它们没有相同的规则。

C&C ++是一样的。 如果他们没有什么不同,他们都会被称为同一件事。

我的解决方法是将其声明为:

 static classfoo foo; 

它适用于我的情况。