C++ 为什么在函数内初始化外部变量会出错?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17090354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does initializing an extern variable inside a function give an error?
提问by Amit Tomar
This code compiles fine:
这段代码编译得很好:
extern int i = 10;
void test()
{
std::cout << "Hi" << i << std::endl;
}
While this code gives an error:
虽然此代码给出了错误:
void test()
{
extern int i = 10;
std::cout << "Hi" << i << std::endl;
}
error: 'i' has both 'extern' and initializer
错误:“i”同时具有“extern”和初始值设定项
I read this in C++ Primer:
我在C++ Primer 中读到了这个:
Any declaration that includes an explicit initializer is a definition. We can provide an initializer on a variable defined as extern, but doing so overrides the extern. An extern that has an initializer is a definition. It is an error to provide an initializer on an extern inside a function.
任何包含显式初始化程序的声明都是定义。我们可以为定义为 extern 的变量提供初始值设定项,但这样做会覆盖 extern。具有初始值设定项的 extern 是一个定义。在函数内部为 extern 提供初始值设定项是错误的。
Can someone provide an explanation as to why this is an error if done locally in a function, while the same is allowed at a global scope?
有人可以解释为什么如果在函数中本地完成这是一个错误,而在全局范围内允许这样做吗?
采纳答案by ChrisCM
The reason defining an external variable inside a function does not make sense is the following:
在函数内部定义外部变量没有意义的原因如下:
When you declare a symbol extern, you are telling the compiler to link all such occurrences of this value into the same symbol. Any occurences of extern int i; in your program would link to the externally defined i. Look at this example:
当您声明一个符号 extern 时,您是在告诉编译器将该值的所有此类出现链接到同一个符号中。任何 extern int i 的出现;在您的程序中将链接到外部定义的 i。看这个例子:
#include <iostream>
using namespace std;
extern int i;
int i = 10;
void test()
{
std::cout << "Hi" << i << std::endl;
}
int main()
{
extern int i;
i++;
test();
}
This example should output hi11. HOwever, if we remove the extern inside main, it will output 10. This is because without extern, i is not linking to the global i, but creating it's own local copy of i.
此示例应输出 hi11。但是,如果我们删除 main 中的 extern,它将输出 10。这是因为没有 extern,i 不会链接到全局 i,而是创建它自己的 i 本地副本。
The reason that defining an extern i inside a function does not make sense, is what if we allowed any function to "define" i. Which function runs first? When does it get defined?
在函数内部定义 extern i 没有意义的原因是,如果我们允许任何函数“定义”i。哪个函数先运行?什么时候定义?
Assume the following example to be valid, what would the output be???
假设下面的例子是有效的,输出会是什么???
#include <iostream>
using namespace std;
extern int i;
int i = 10;
void test()
{
std::cout << "Hi" << i << std::endl;
}
void test2() {
extern int i = 1000;
std::cout<< "HI" << i << std::endl;
}
void test3() {
extern int i;
i = 1000;
std::cout<< "HI" << i << std::endl;
}
int main()
{
extern int i;
i++;
test();
i = 0;
test2();
}
Should the output of test2 be 0, or 1000? Also look at my test3, here we are concisely saying, link my i to the externally defined i, and assign it's value as 1000. This is very different from trying to "initialize" a value.
test2 的输出应该是 0 还是 1000?也看看我的 test3,这里我们简洁地说,将我的 i 链接到外部定义的 i,并将它的值指定为 1000。这与尝试“初始化”一个值非常不同。
In short, extern variables really only make sense as globals, and should be defined in global scope. In your examples, the first version doesn't compile either for me. I find this interesting. It might be worth looking at the standards docs to see if this is defined concisely, or if your compiler might be handling this in a way designed to add additional protection...
简而言之,extern 变量实际上只作为全局变量才有意义,并且应该在全局范围内定义。在您的示例中,第一个版本也不适合我编译。我觉得这很有趣。可能值得查看标准文档,看看这是否定义简洁,或者您的编译器是否可能以旨在增加额外保护的方式处理此问题...
回答by Mike Seymour
By adding an initialiser to the declaration, it becomes a definition of the global variable. It's equivalent to the same definition without extern
, which is what your book means when it says it "overrides the extern".
通过在声明中添加初始化器,它成为全局变量的定义。它相当于没有 的相同定义extern
,这就是你的书说它“覆盖外部”时的意思。
While global variables can be declared (using extern
) inside a function, they cannot be defined there, only at namespace scope. That's why the second snippet is an error.
虽然全局变量可以extern
在函数内声明(使用),但不能在函数内定义,只能在命名空间范围内定义。这就是为什么第二个片段是错误的。
If you want to know why the designers of C (whence these rules came to C++) chose to allow declarations but not definitions here, then I'm afraid I don't know the language's history in enough detail to answer.
如果你想知道为什么 C 的设计者(这些规则来自 C++)选择在这里允许声明而不是定义,那么恐怕我对语言的历史了解不够详细,无法回答。
回答by yuan
At first ,you should familiar with the conception of linkage and the meaning of extern linkage:
首先,您应该熟悉链接的概念和外部链接的含义:
A name is said to have linkagewhen it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
When a name has externallinkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
--3.5.6.2 n3242
当一个名称可能表示与另一个作用域中的声明引入的名称相同的对象、引用、函数、类型、模板、命名空间或值时,就说它具有链接:
当名称具有外部链接时,它所表示的实体可以被来自其他翻译单元的作用域或来自同一翻译单元的其他作用域的名称所引用。
--3.5.6.2 n3242
The function of static
which is differ from extern
,extern
is just a request,static
is a command.
其功能static
不同于extern
,extern
只是一个请求,static
是一个命令。
The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage.
- If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration.
- If there is more than one such matching entity, the program is ill-formed.
- Otherwise, if no matching entity is found, the block scope entity receives external linkage.
--3.5.6.6 n3242
块作用域中声明的函数名和块作用域 extern 声明中声明的变量名有联系。
- 如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明相同的实体并接收先前声明的链接。
- 如果存在多个这样的匹配实体,则程序格式错误。
- 否则,如果未找到匹配实体,则块范围实体接收外部链接。
--3.5.6.6 n3242
Therefore,in block scope the procedure below is recommend to do:
因此,在块范围内,建议执行以下过程:
extern int i;//declare it,request the linkage according to 3.5.6.6 above
i = 10;//modify it when has link to a defination
For the global extern declaration is possibly convert form
对于全局 extern 声明可能是转换形式
extern int i =10;
to
到
extern int i;//include in .hpp is recommended
int i =10;//global or namespace variable defination
回答by Super Cat
The simplest way to put it:
最简单的表达方式:
The purpose of the extern
keyword is to declare an object without defining it. By defining it, you're basically telling the compiler "Do not assign a value but assign a value". That doesn't make sense - It should never be done, inside oroutside a function. Most compilers will either warn you and proceed anyway, or they won't compiler at all and give an error.
extern
关键字的目的是声明一个对象而不定义它。通过定义它,您基本上是在告诉编译器“不要赋值,而是赋值”。这是没有意义的 - 无论是在函数内部还是外部,都不应该这样做。大多数编译器要么会警告您并继续进行,要么根本不会编译并给出错误。
Though it's beyond the scope of this question to explain in detail whatextern
does, you may find it useful to read the answers for this question.
虽然详细解释什么超出了这个问题的范围,extern
但您可能会发现阅读这个问题的答案很有用。
回答by Don Slowik
extern
variables are initialized before any function runs:
en.cppreference.com/w/cpp/language/initialization#Non-local_variables
extern
在任何函数运行之前初始化变量:
en.cppreference.com/w/cpp/language/initialization#Non-local_variables
If it was declared static
rather than extern
within a function block, it would still have static storage duration, but its' linkagewould be localto that function vs. external. So it would be initialized when the execution first runs through that line within the function:
en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables
如果它被声明static
而不是extern
在功能块内,它仍然具有静态存储持续时间,但它的链接将是该函数的本地链接,而不是外部链接。因此,当执行第一次通过函数中的那一行时,它将被初始化:
en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables
So it's ok to initialize static
variables in a function block, but not ok to initialize extern
variables there.
所以static
在功能块中初始化变量是可以的,但在extern
那里初始化变量就不行了。