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

发布于 2024-11-10 07:14:08 字数 583 浏览 0 评论 0原文

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

为什么 C++ 允许这样做,而 C 不允许?与 C 相比,为什么 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;
}

Multiple definition of a global variable is not allowed in C or C++ due to the One Definition Rule. However, in C++ a const global variable can be defined in multiple compilation units with no error. This is not the same as in C.

Why does C++ allow this while C does not? Why does the usage and behaviour of a const global differ from a non-const global in this way in C++ compared to C? What is happening under the covers with C++ and C with respect to const?

For example this is allowed in C++, but wrong in C:

// Foo.cpp
const int Foo = 99;

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

And this is fine with C, but wrong with C++:

// Foo.cpp
const int Foo = 99;

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

娇女薄笑 2024-11-17 07:14:08
// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

命名空间范围内的 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;
}
// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

const variable at namespace scope has internal linkage. So they're basically two different variables. There is no redefinition.

From @David's comment, 3.5/3 [basic.link]:

A name having namespace scope (3.3.5)
has internal linkage if it is the name
of
— an object, reference, function or
function template that is explicitly
declared static or,
— an object or
reference that is explicitly declared
const and neither explicitly declared
extern nor previously declared to have
external linkage
; or
— a data member
of an anonymous union.


In the second case, you should be doing this (correct way):

//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;
}
蓬勃野心 2024-11-17 07:14:08

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

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

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

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

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

I think you are asking for the rationale and not the specific language rule that allows this.

The rationale for this is that it makes const variables much easier to use. It gives a typed replacement for one common use of #define.

Instead of #define MAX_COUNT 211 you can use const int max_count = 211; in exactly the same way, e.g. a shared header file, without having to worry about where to put the one definition.

You can't legally change the value of a const object so there's no visible difference between having one object and multiple objects with the same value.

As you can put a definition of a const object in a header file it makes trivial for the compiler to use the value directly at the compilation stage without such optimizations having to be delayed to a link-time fixup.

我们的影子 2024-11-17 07:14:08

基本上,在 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 中,这不存在,它们只是变量这恰好是不可修改的。

Basically, in C++, const, non-local variables are genuine constant expressions, or constexpr. This permits plenty of things, like TMP.

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

In C, they are just a variable that cannot be modified. That is,

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

Is quite equivalent to

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

Effectively, C++ promotes some kinds of const variable to a new category, constexpr, whereas in C, this does not exist and they are just variables which happen to be unmodifiable.

不打扰别人 2024-11-17 07:14:08

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

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

C& C++也是一样的。如果它们没有不同,它们就会被称为同一个东西。

Why do English people spell COLOUR, whereas American people spells it COLOR?

They are 2 different languages from the same base, but they don't have the same rules.

C & C++ are the same. If they weren't different, they would both be called the same thing.

苏辞 2024-11-17 07:14:08

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

static classfoo foo;

它适用于我的情况。

My workaround was declaring it as :

static classfoo foo;

it worked in my situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文