关于范围和寿命

Ced*_* H. 4 c++

引用"C++编程语言"(特别版,第4.9.6节"对象和左值"),众所周知:

[...]函数中声明的对象在遇到其定义时创建,并在其名称超出范围时销毁

好 !在4.9.4节中:

名称只能用于程序文本的特定部分.对于在函数中声明的名称,该范围从其声明点延伸到其声明发生的块的末尾.

听起来都不错!

但我的问题是:当控件到达块的末尾时,如何销毁(auto)变量?一个问题:实际情况如此吗?

例如:

int main()
{
  int* c = 0;
  {
    int b = 999;
    c = &b;
  } // End of the scope of b...
  std::cout << b; // ... so this is illegal
  // But ...
  std::cout << *c; // ... is OK, so 'b' has not really been destroyed
}
Run Code Online (Sandbox Code Playgroud)

我知道在退出函数范围时会破坏局部变量,因为函数调用中涉及到堆栈相关的事情.但是当退出一个简单的{ // ... }块时,没有任何反应.

它是否是一种特定的语言导致未定义的行为(在我的情况下,最后一个cout实际上是未定义的)但实际上在执行时没有效果(实际上没有执行任何操作来销毁对象)?

谢谢 !

编辑1:我不考虑静态变量.

编辑2:如果变量是带有析构函数的对象,我很清楚,我问的是非对象变量.

小智 9

您的示例中的代码确实是未定义的行为,它似乎适用于这样的简单示例.但是编译器可以选择重用用于存储变量b的槽.或者由于函数调用而导致数据被压入堆栈,因此可能会将其销毁.


sha*_*oth 5

在你的例子中

std::cout << *c;
Run Code Online (Sandbox Code Playgroud)

是未定义的行为 - 您尝试访问生命周期已结束的变量.碰巧的是,内存地址仍然是映射到程序的地址空间,没有人已经overwitten内存,因此它似乎工作.

你不应该依赖它,你永远不应该写那样的代码.什么能可能发生的是,中断将会发生暂停你的程序,让其他程序运行.如果出现这种情况很多操作系统当前CPU状态(寄存器值)保存到同一组,这会导致覆盖与结束寿命临时工.