常量和全局

发布于 2024-12-29 20:10:27 字数 735 浏览 2 评论 0原文

此代码将在 C++ 中产生错误

// Foo.cpp
const int Foo = 99;

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

,因为许多人给出的原因是全局 const 具有内部作用域,并且它是默认静态的。

解决方案是:-

    //Foo.h
    extern const int Foo; 

    // Foo.cpp
    #include "Foo.h"
    const int Foo = 99; 

    // Main.cpp
    #include "Foo.h"
    int main()
    {
       cout << Foo << endl;
    }

我曾经认为 extern 用于告诉编译器用于 indentifer 的内存已经分配在其他文件中的某处。
对上面的代码应用相同的逻辑,任何人都可以解释这里发生的事情,或者 extern 在 c++ 中有不同的含义??
在此处输入链接说明
还要考虑这个页面它破坏了我所有的直觉..

This code will produce error in c++

// Foo.cpp
const int Foo = 99;

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

Reason as given by many is global const has internal scope and it is default static.

solution to this is :-

    //Foo.h
    extern const int Foo; 

    // Foo.cpp
    #include "Foo.h"
    const int Foo = 99; 

    // Main.cpp
    #include "Foo.h"
    int main()
    {
       cout << Foo << endl;
    }

I used to think that extern is used to tell compiler that memory for the indentifer is already allocated somewhere in other files.
Applying same logic on above code can anyone explain what is happening here or extern has different meaning in c++??
enter link description here
Also consider this page it is spoiling my all intuitions..

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

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

发布评论

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

评论(2

×纯※雪 2025-01-05 20:10:27

如果我们只需要声明一个全局常量(而不是static)怎么办? extern 如何帮助执行此操作?

使用 extern 限定符声明的 const 对象具有外部链接。
因此,如果您想在多个翻译单元中使用 const,请为其添加 extern 限定符。

全局变量默认具有外部链接,为什么 const 全局变量默认具有内部链接?

参考:
C++03 标准附录 C 兼容性 C.1.2 第 3 条:基本概念

更改:显式声明为 const 且未显式声明为 extern 的文件作用域名称具有内部链接,而在 C 中则具有外部链接

基本原理:因为 const 对象可以用作 C++ 中的编译时值,所以此功能促使程序员为每个 const 提供显式的初始值设定项。此功能允许用户将 const 对象放入许多编译单元中包含的头文件中。


通过遵循一个简单的规则来避免混淆:

默认情况下,对于非常量符号来说链接是外部的,对于常量符号来说链接是静态的(内部的)。

What if we have to declare only a global constant(not static)? How extern help in doing this?

A const object declared with extern qualifier has external linkage.
So if you want to use a const across multiple Translation units, add an extern qualifier to it.

While a global variable has external linkage by default,why a const global has internal linkage by default?

Reference:
C++03 Standard Annex C Compatibility C.1.2 Clause 3: basic concepts

Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage

Rationale: Because const objects can be used as compile-time values in C + +, this feature urges programmers to provide explicit initializer values for each const. This feature allows the user to put const objects in header files that are included in many compilation units.


Avoid the confusion by following a simple rule:

By default Linkage is external for non-const symbols and static (internal) for const symbols.

守不住的情 2025-01-05 20:10:27

快速提醒,以便清楚我们正在讨论的内容:

int const a;            //  illegal
int const a = 42;       //  definition, internal linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  definition , external linkage

请注意,如果没有 const,上面的前两个声明都是
具有外部链接的定义。这绝不是正交的,并且
不是很直观,但这就是现行规则的规定。

给出 const 外部链接的问题是可能存在
具有外部链接的对象只有一个定义,并且具有一个
例外,只有定义可以有初始化程序。这意味着
对于具有外部链接的常量,实际值(如果
const 用于常量表达式)只能在一个中可见
翻译单位。这可能就是赋予 const 的动机
默认内部链接。

当然,这至少会导致模板出现无穷无尽的问题
理论上;如果以下标头具有未定义的行为
包括多个翻译单元:

#include <std::vector>

int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
    dest.push_back( fixedValue );
}

该标准规定,内联函数和模板不仅必须具有
相同的标记序列,但所有符号都必须绑定
每个翻译单元中的同一个对象,或者违反了
单一定义规则。并且由于 fixedValue 没有外部
链接,每个翻译单元中有一个唯一的实例。 (有
异常如果符号引用const对象并且
立即左值到右值的转换。自从
std::vector::push_back 通过引用获取其参数,但是,
没有立即左值到右值的转换,我们得到了 undefined
行为。)

当然,任何拥有模板的人:

template <int& r> ...

也无法使用 fixedValue 实例化它。

内部联系的原因当然是有历史原因的。今天,
编译器必须能够支持以下内容:

struct X
{
    static int const a = 42;    //  declaration!!!, external linkage
};

以及函数的各种重复定义。这将是
扩展允许初始化程序的规则相对简单
在类中对命名空间范围内的变量进行声明,以给出
类似于:

int const a;                //  illegal
int const a = 42;           //  definition, external linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  declaration, external linkage

这将恢复正交性(即使需要额外的输入)。它
也会破坏几乎所有现有的代码。

另一种选择是处理 const 变量定义
与今天处理函数模板完全相同:您可以有多个
定义,但它们必须全部相同。这可能会避免
大多数(如果不是全部)代码损坏。

A quick reminder, so that it is clear what we are talking about:

int const a;            //  illegal
int const a = 42;       //  definition, internal linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  definition , external linkage

Note that without the const, the first two declarations above are both
definitions with external linkage. This is anything but orthogonal, and
not very intuitive, but this is what the current rules say.

The problem with giving a const external linkage is that there can be
only one definition of an object with external linkage, and with one
exception, only the definition can have an initializer. This means that
for a const with external linkage, the actual value (necessary if the
const is to be used in a constant expression) can only be visible in one
translation unit. This is probably the motivation for giving const
internal linkage by default.

Of course, this causes no end of problems with templates, at least
theoretically; the following header has undefined behavior if it is
including in more than one translation unit:

#include <std::vector>

int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
    dest.push_back( fixedValue );
}

The standard says that not only must inline functions and templates have
an identical sequence of tokens, but that all of the symbols must bind
to the same object in every translation unit, or there is a violation of
the one definition rule. And since fixedValue does not have external
linkage, there is a unique instance in each translation unit. (There is
an exception if the symbol refers to a const object and there is
an immediate lvalue to rvalue conversion. Since
std::vector<int>::push_back takes its argument by reference, however,
there is no immediate lvalue to rvalue conversion, and we get undefined
behavior.)

And of course, anyone with a template:

template <int& r> ...

cannot instantiate it with fixedValue either.

The reason for the internal linkage is, of course, historical. Today,
compilers must be able to support things like:

struct X
{
    static int const a = 42;    //  declaration!!!, external linkage
};

and all sorts of duplicate definitions for functions. It would be
relatively trivial to extend the rules allowing initializers on a
declaration in a class to variables at namespace scope, to give
something like:

int const a;                //  illegal
int const a = 42;           //  definition, external linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  declaration, external linkage

This would restore orthogonality (even if it required extra typing). it
would also break almost all existing code.

Another alternative would be to treat const variable definitions
exactly as function templates are treated today: you can have multiple
definitions, but they must all be identical. This would probably avoid
most, if not all, code breakage.

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