此代码将在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用于告诉编译器,已经在其他文件中的某处将分配的内存分配给了。
在上面的代码中应用相同的逻辑可以解释这里发生的事情,或者extern在c ++中有不同的含义
enter link description here
还要考虑这个页面,这会破坏我的所有直觉......
答案 0 :(得分:7)
如果我们必须只声明一个全局常量(不是static
)怎么办? extern
如何帮助您做到这一点?
使用const
限定符声明的extern
对象具有外部链接
因此,如果您想在多个翻译单元中使用const
,请为其添加extern
限定符。
默认情况下,全局变量具有外部链接,为什么const全局默认具有内部链接?
参考:
C ++ 03标准附录C兼容性C.1.2第3条:基本概念
更改:显式声明为const且未显式声明为extern的文件范围名称具有内部链接,而在C中则具有外部链接
基本原理:因为const对象可以在C ++中用作编译时值,所以这个特性促使程序员为每个const提供显式的初始化值。此功能允许用户将const对象放在许多编译单元中包含的头文件中。
遵循一条简单的规则避免混淆:
默认情况下,Linkage对于非const符号是外部的,对于const符号是静态的(内部的)。
答案 1 :(得分:3)
快速提醒,以便我们所说的很清楚:
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用于常量表达式)只能在一个中可见
翻译单位。这可能是给予const
的动机
内部链接默认情况下。
当然,这至少会导致模板无法解决问题 理论上;如果是,则以下标头具有未定义的行为 包括在多个翻译单元中:
#include <std::vector>
int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
dest.push_back( fixedValue );
}
标准规定,不仅内联功能和模板必须具备
一个相同的标记序列,但所有符号必须绑定
每个翻译单元中的同一个对象,或者有违反
一个定义规则。由于fixedValue
没有外部因素
链接,每个翻译单元都有一个唯一的实例。 (有
一个例外如果符号引用const
对象和那么
rvalue转换的直接左值。以来
然而,std::vector<int>::push_back
通过引用来论证其论点,
rvalue转换没有立即左值,我们得到了未定义
行为)。
当然,任何人都有模板:
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
变量定义
就像今天处理的功能模板一样:你可以有多个
定义,但它们必须完全相同。这可能会避免
大多数(如果不是全部)代码破坏。