为什么在C++中而不是在C中允许对const全局变量进行多重定义?

Ash*_*ppa 28 c c++ const one-definition-rule

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

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

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

// Foo.cpp
const int Foo = 99;

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

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

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 28

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
Run Code Online (Sandbox Code Playgroud)

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

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

具有命名空间作用域(3.3.5)的名称具有内部链接(如果它是
- 一个显式声明为静态的对象,引用,函数或函数模板的名称),
或者是显式声明为const且未显式声明的对象或引用的名称外部或以前宣布有外部联系 ; 或
- 匿名联盟的数据成员.


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

//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;
}
Run Code Online (Sandbox Code Playgroud)

  • 在标准... 3.5/3 [basic.link]:*具有命名空间作用域(3.3.5)的名称具有内部链接,如果它是 - 一个显式声明为静态的对象,引用,函数或函数模板的名称或者, - **显式声明为const的对象或引用,既未显式声明为extern,也未声明为具有外部链接;**或 - 匿名联合的数据成员.* (6认同)

CB *_*ley 7

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

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

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

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

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


Pup*_*ppy 6

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

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> arr;
}
Run Code Online (Sandbox Code Playgroud)

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

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

相当于

int five = 5;
int main() {
    int x[five];
}
Run Code Online (Sandbox Code Playgroud)

实际上,C++将某些类型的const变量提升到一个新类别,constexpr而在C语言中,它不存在,它们只是碰巧不可修改的变量.