简体   繁体   English

变量的作用域与生命周期

[英]Scope vs. Lifetime of Variable

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;


}

What is Scope?什么是范围?

Scope is the region or section of code where a variable can be accessed.范围是可以访问变量的区域或代码段。

What is a lifetime?什么是一生?

Lifetime is the time duration where an object/variable is in a valid state.生命周期是对象/变量处于有效状态的持续时间。

For, Automatic/Local non-static variables Lifetime is limited to their Scope .对于,自动/本地非静态变量Lifetime仅限于它们的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.因此,名称自动开始。

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.在您的示例中, *p范围是创建后的整个函数体。
However, x is a non-static local/automatic variable and hence the lifetime of x ends with it's scope ie the closing brace of } in which it was created, once the scope ends x does not exist.然而, x是一个非静态局部/自动变量,因此x的生命周期以其作用域结束,即创建它的}的右大括号,一旦作用域结束x就不存在。 *p points to something that doesn't exist anymore. *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.请注意,技术上x不存在于其范围之外,但是可能会发生编译器没有删除x的内容,并且一个人可能能够通过指针访问超出其范围的x内容(就像您所做的那样)。但是,代码这不是有效的 C++ 代码。 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值是完整的),并且不应期望从这样的代码中可以观察到行为。

C11 Section 6.2.1 Paragraph 2 C11 第 6.2.1 节第 2 段

For each different entity that an identifier designates, the identifier is visible (ie, 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.另一方面,例如,说一个static局部变量,在这种情况下,作用域是块本地的,所以我们不能在块外通过它的名字访问,但生命周期是整个程序,所以我们可以使用程序运行时变量在程序中任何位置的地址。 This example should help get the difference.这个例子应该有助于区分。

Objects (ie the actual underlying things that store values) have lifetimes.对象(即存储值的实际底层事物)具有生命周期。

Variables (ie the things used to refer to objects) have scope.变量(即用来指代对象的东西)有作用域。

Either way, y = *p invokes undefined behaviour;无论哪种方式, y = *p调用未定义的行为; the object referred to by x is automatic , its lifetime ends when x goes out of scope. x引用的对象是自动的,当x超出范围时,它的生命周期结束。

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 object is no longer there.访问变量在所有情况下都是未定义的行为,因为并非所有情况都必须相等,并且如果变量具有非平凡的析构函数,它将在作用域的末尾被调用,因此内存是否存在无关紧要:该对象不再存在。 That being said, in many cases compilers will not release the memory in the function (ie 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.也就是说,在许多情况下,当变量超出范围时,编译器不会释放函数中的内存(即它们不会重新设置帧指针),但它们可能会重用相同的空间来保存同一函数中的其他变量。

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.

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 的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM