C++ 变量的作用域与生命周期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11137516/
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
Scope vs. Lifetime of Variable
提问by user695652
What is the relation between the scope and the lifetime of a variable? If a variable is out of scope, is the memory of it allowed to be overwritten by another variable, or is the space reserved until the function is left.
变量的作用域和生命周期之间有什么关系?如果一个变量超出范围,它的内存是否允许被另一个变量覆盖,或者是否保留空间直到函数离开。
I am aksing because I want to know whether the code below actually works, or whether it can be that *p might be undefined
我在 aksing 因为我想知道下面的代码是否真的有效,或者 *p 是否可能是未定义的
foo() {
int *p;
{
int x = 5;
p = &x;
}
int y = *p;
}
回答by Alok Save
What is Scope?
什么是范围?
Scopeis the region or section of code where a variable can be accessed.
范围是可以访问变量的区域或代码段。
What is a lifetime?
什么是一生?
Lifetimeis the time duration where an object/variable is in a valid state.
生命周期是对象/变量处于有效状态的持续时间。
For, Automatic/Local non-static variables Lifetime
is limited to their Scope
.
In other words, automatic variables are automagically destroyed once the scope({
,}
) in which they are created ends. Hence the name automatic to begin with.
因为,自动/本地非静态变量Lifetime
仅限于它们的Scope
.
换句话说,一旦创建它们的作用域( {
, }
) 结束,自动变量就会自动销毁。因此,名称自动开始。
What is wrong in your code example?
您的代码示例有什么问题?
So Yes your code has an Undefined Behavior.
所以是的,你的代码有一个Undefined Behavior。
In your example scope of *p
is entire function body after it was created.
However, x
is a non-static local/automatic variable and hence the lifetime of x
ends with it's scope i.e the closing brace of }
in which it was created, once the scope ends x
does not exist. *p
points to something that doesn't exist anymore.
在您的示例中,范围*p
是创建后的整个函数体。
然而,x
是一个非静态的局部/自动变量,因此一旦范围结束就不存在x
,其生命周期结束于它的范围,即}
创建它的右大括号x
。*p
指向不再存在的东西。
Note that technically x
does not exist beyond its scope however it might happen that the compiler did not remove the contents of x
and one might be able to access contents of x
beyond its scope through a pointer(as you do).However, a code which does this is not a valid C++ code. It is a code which invokes Undefined Behaviour. Which means anything can happen(you might even see value of x
being intact) and one should not expect observable behaviors from such a code.
请注意,技术上x
不存在超出其范围,但是可能会发生编译器没有删除 的内容,x
并且一个人可能能够x
通过指针访问超出其范围的内容(正如您所做的那样)。但是,执行此操作的代码不是有效的 C++ 代码。这是一个调用未定义行为的代码。这意味着任何事情都可能发生(您甚至可能会看到x
完整无缺的价值),并且不应期望从这样的代码中可以观察到行为。
回答by phoxis
C11 Section 6.2.1 Paragraph 2
C11 第 6.2.1 节第 2 段
For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces
对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本区域内可见(即,可以使用)。由同一标识符指定的不同实体要么具有不同的作用域,要么位于不同的名称空间中
.
.
C11 Section 6.2.4 Paragraph 2
C11 第 6.2.4 节第 2 段
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it.
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储空间。
In your case x
is local to the block, and so is its lifetime, therefore x
cannot be accessed by its name outside the block, also because its lifetime is limited to its block the address of x
will not be reserved anymore after leaving the block, thus will result in undefined behaviour.
在您的情况下x
是块本地的,因此它的生命周期也是如此,因此x
不能在块外通过其名称访问,也因为它的生命周期仅限于它x
的块,离开块后将不再保留其地址,因此将导致未定义的行为。
On the other hand, for example, say a static
local variable, in this case the scope is local to the block and so we can't access by its name outside the block, but the lifetime is the entire program, so we can use the address of the variable anywhere in the program while it is running. This example should help get the difference.
另一方面,例如,说一个static
局部变量,在这种情况下,作用域是块本地的,所以我们不能在块外通过它的名字访问,但生命周期是整个程序,所以我们可以使用程序运行时变量在程序中任何位置的地址。这个例子应该有助于区分。
回答by Oliver Charlesworth
Objects (i.e. the actual underlying things that store values) have lifetimes.
对象(即存储值的实际底层事物)具有生命周期。
Variables (i.e. the things used to refer to objects) have scope.
变量(即用来指代对象的东西)有作用域。
Either way, y = *p
invokes undefined behaviour; the object referred to by x
is automatic, its lifetime ends when x
goes out of scope.
无论哪种方式,都会y = *p
调用未定义的行为;引用的对象x
是自动的,当x
超出范围时,其生命周期结束。
回答by David Rodríguez - dribeas
What is the relation between the scope and the lifetime of a variable?
变量的作用域和生命周期之间有什么关系?
As Oli stated, variables have scope and objects lifetime. The scope of a variable and the lifetime of it are bound, but you can have objects whose lifetime extends beyond the scope on which they were created:
正如奥利所说,变量有作用域和对象生命周期。变量的范围和它的生命周期是绑定的,但是你可以拥有生命周期超出创建它们的范围的对象:
int* f() {
int *p // Variable p
= new int(1); // object (call it x)
return p; // p scope ends, p lifetime ends, x survives
}
int main() {
int *q // Variable q
= f(); // ... points to x
delete q; // x lifetime ends, q is in scope, q is alive
}
In your particular case, x
variable ends it's lifetime when the scope in which it was created is closed, so you have undefined behavior.
在您的特定情况下,x
变量在创建它的范围关闭时结束其生命周期,因此您具有未定义的行为。
If a variable is out of scope, is the memory of it allowed to be overwritten by another variable, or is the space reserved until the function is left.
如果一个变量超出范围,它的内存是否允许被另一个变量覆盖,或者是否保留空间直到函数离开。
This is a detail of implementation. Accessing the variable is undefined behavior in all cases and because not all cases must be equal, and if the variable had a non trivial destructor, it would be called at the end of the scope, so whether the memory is there or not is irrelevant: the objectis no longer there. That being said, in many cases compilers will not releasethe memory in the function (i.e. they will not reseat the frame pointer) when a variable goes out of scope, but they might reuse the same space to hold other variables in the same function.
这是一个实现细节。访问变量在所有情况下都是未定义的行为,因为并非所有情况都必须相等,如果变量有一个非平凡的析构函数,它将在作用域的末尾被调用,因此内存是否存在是无关紧要的:该对象不再存在。也就是说,在许多情况下,当变量超出范围时,编译器不会释放函数中的内存(即它们不会重新设置帧指针),但它们可能会重用相同的空间来保存同一函数中的其他变量。
回答by tez
I have run your program and the output is 5.The output is still 5 though the x variable is destroyed after the second '}' is because the memory location is not overwritten by any other variable.if you have a lot of code after after the end of second scope,It is highly likely that the memory location previously owned by 'x' is overwritten.
我已经运行了你的程序,输出是 5。尽管 x 变量在第二个 '}' 之后被销毁,但输出仍然是 5 是因为内存位置没有被任何其他变量覆盖。如果之后你有很多代码第二个作用域的结尾,很可能之前由 'x' 拥有的内存位置被覆盖了。
int x = 5;
*p = &x;
} // x lifetime ends after this.but the number '5' is still there in that memory.
//but it is possible to assign this memory (which previously belong to x) to a new var.
回答by Agent_L
Standard defines that the memory is allowed to be overwritten once scope is left. Compiler implementation makes it reserved and freed. Compile-time optimizations might move allocation of stack so they will no longer reflect your order.
标准定义了一旦离开范围就允许覆盖内存。编译器实现使其保留和释放。编译时优化可能会移动堆栈的分配,因此它们将不再反映您的顺序。
Your code does invoke undefined behaviour and should not be used. Your code might actually work, since writing value of y occurs AFTER taking the value p points to.
您的代码确实调用了未定义的行为,不应使用。您的代码实际上可能有效,因为在取 p 指向的值之后写入 y 的值。