28

由于单一定义规则,在 C 或 C++ 中不允许对全局变量进行多重定义。但是,在 C++ 中,一个 const 全局变量可以在多个编译单元中定义而不会出错。这与 C 中的不同。

为什么 C++ 允许这样做,而 C 不允许?与 C 相比,为什么 C++ 中 const 全局变量的用法和行为与非 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;
}

这对 C 来说很好,但对 C++ 来说是错误的:

// Foo.cpp
const int Foo = 99;

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

6 回答 6

28
// 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;
}
于 2011-05-30T08:21:17.800 回答
7

我认为您要的是基本原理,而不是允许这样做的特定语言规则。

这样做的理由是它使const变量更易于使用。它为#define.

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

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

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

于 2011-05-30T08:38:19.160 回答
6

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

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> 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 中,这不存在,它们只是碰巧不可修改的变量。

于 2011-05-30T08:59:44.960 回答
3

看起来const 实际上并没有生成外部符号

于 2011-05-30T08:22:53.113 回答
-1

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

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

C 和 C++ 是一样的。如果它们没有不同,它们将被称为同一个东西。

于 2012-05-04T13:00:01.543 回答
-3

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

static classfoo foo;

它适用于我的情况。

于 2013-10-22T02:32:48.327 回答