C++ 常量与全局

C++ 常量与全局,c++,global-variables,constants,extern,C++,Global Variables,Constants,Extern,这段代码将在c语言中产生错误++ // Foo.cpp const int Foo = 99; // Main.cpp extern const int Foo; int main() { cout << Foo << endl; return 0; } 许多人给出的理由是,全局常量有内部作用域,它是默认静态的 解决办法是:- //Foo.h extern const int Foo; // Foo.cpp

这段代码将在c语言中产生错误++

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}    
许多人给出的理由是,全局常量有内部作用域,它是默认静态的

解决办法是:-

    //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的内存已经分配到了其他文件的某个地方。 在上面的代码中应用相同的逻辑,有人能解释这里发生的事情或者在C++中有不同的含义吗? 也考虑这个页面,它破坏了我所有的直觉。

如果我们必须声明一个全局常数而不是静态的呢?extern如何帮助做到这一点

使用外部限定符声明的常量对象具有外部链接。 因此,如果要跨多个翻译单元使用常量,请向其添加外部限定符

虽然默认情况下全局变量有外部链接,但为什么常量全局变量默认情况下有内部链接

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

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

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

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

默认情况下,非常量符号的链接是外部链接,常量符号的链接是静态内部链接。

如果我们必须只声明全局常量而不是静态链接,该怎么办?extern如何帮助做到这一点

使用外部限定符声明的常量对象具有外部链接。 因此,如果要跨多个翻译单元使用常量,请向其添加外部限定符

虽然默认情况下全局变量有外部链接,但为什么常量全局变量默认情况下有内部链接

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

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

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

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


默认情况下,非常量符号的链接是外部链接,常量符号的链接是静态内部链接。

快速提醒,以便清楚地了解我们所说的内容:

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的动机 默认情况下为内部链接

当然,这至少会给模板带来无尽的问题 理论上;以下标头具有未定义的行为(如果 包括在多个翻译单元中:

#include <std::vector>

int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
    dest.push_back( fixedValue );
}
也无法使用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
这将恢复正交性,即使它需要额外的键入。信息技术 也会破坏几乎所有现有的代码

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

一个快速提醒,以便清楚地了解我们在谈论什么:

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的动机 默认情况下为内部链接

当然,这至少会给模板带来无尽的问题 理论上;以下标头具有未定义的行为(如果 包括在多个翻译单元中:

#include <std::vector>

int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
    dest.push_back( fixedValue );
}
也无法使用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
这将恢复正交性,即使它需要额外的键入。信息技术 也会破坏几乎所有现有的代码

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

extern const a;是无效的C++,我不认为。你需要像extern const int a这样的东西;您在第一个突出显示的块中有错误,但在最后一个块中是正确的。@RobertCrovella我认为它甚至都不是有效的C,今天,如果它是有效的,那肯定是不好的做法。我已经修好了;是无效的C++,我不认为。你需要像extern const int a这样的东西;您在第一个突出显示的块中有错误,但在最后一个块中是正确的。@RobertCrovella我认为它甚至都不是有效的C,今天,如果它是有效的,那肯定是不好的做法。我已经修好了。