The extern
关键字是说:这只是一个声明。
对于一个变量,您只需要一个定义,即。没有声明extern
别的地方:
// foo.h
extern int i;
// foo.cc
#include "foo.h"
int i; // definition
// bar.cc
#include "foo.h"
int main () {
++i; // modifies global variable
}
特别规则const
一个常见的用例const
变量是在头文件中定义常量,然后在程序中的其他地方使用它们:
// my_constants.h
const int NumHoursInDay = 24;
const int NumMinutesInHour = 60;
如果这些变量不是const
,然后包括my_constants.h
由于变量有多个定义,进入不同的翻译单元(源文件+它们的头)会导致链接器错误。
标准委员会认为这将是一个足够常见的用例,因此他们实际上为声明的变量制定了特殊规则const
,C++ '03 7.1.5/2:
在命名空间范围内声明的具有 const 限定类型的对象具有
内部链接,除非它被明确声明为外部或除非它是
先前声明具有外部链接。
这意味着每个翻译单元都将拥有自己的私有副本const
多变的。链接器不会尝试将它们合并在一起,因此不会出现错误。
所以第一点是你实际上可以删除extern
从你的例子中,你的代码将正确编译和链接,这一切都是因为这种特殊行为const
.
但是,无论出于何种原因,如果您决定首先声明变量,然后在项目中使用单个定义,您可能已经注意到以下内容仍然会生成链接器错误:
// foo.h
extern const int i;
// foo.cc
const int i = 0;
这是因为链接器希望找到一个定义i
在 foo.h 中并且作为i
在 foo.cc 中具有内部链接(即,它在该翻译单元之外是不可见的),链接器不会认为这些对象是相同的。
这可以通过查看标准引用的末尾来解决:
或者除非它之前已声明具有外部链接。
我们需要做的是告诉编译器i
在 foo.cc 中应该通过首先声明它来具有外部链接extern
and then定义它没有extern
.
// foo.cc
extern const int i;
const int i = 0;
最好的方法是包含我们的头文件,这样我们就只有一个声明:
// foo.cc
#include "foo.h" // contains the extern declaration of 'i'
const int i = 0;
数组维数
最后一点是数组维度必须是常量表达式。增加了这里的混乱,extern const
当前翻译单元中未定义的变量不被视为常量表达式:
extern const int ArrayDim;
int array[ArrayDim]; // Illegal C++
该代码可以编译,特别是如果您使用 g++,因为有一个名为“可变长度数组”的 C 语言功能。编译器在幕后隐藏内存分配来支持这一点。
由于您打算在多个翻译单元中使用常量,并且需要将其用作常量表达式那么最好的选择是在头文件中定义常量:
// my_constants.h
const int x = 10;
#include<iostream>
#include "my_constants.h"
using namespace std;
int main()
{
int _array[x];
cout << x << endl;
}