范围与变量的生命周期

use*_*652 20 c++ scope

变量的范围和生命周期之间的关系是什么?如果变量超出范围,则其内存是否允许被另一个变量覆盖,或者在保留该函数之前保留该空间.

我很想,因为我想知道下面的代码是否真的有效,或者是否可能是*p未定义

foo() {
  int *p;
  {
    int x = 5; 
    p = &x;
  }
  int y = *p;


}
Run Code Online (Sandbox Code Playgroud)

Alo*_*ave 28

什么是范围?

范围是可以访问变量的代码的区域或部分.

什么是一生?

生命周期是对象/变量处于有效状态的持续时间.

对于,自动/本地非静态变量Lifetime仅限于它们Scope.
换句话说,一旦创建它们的范围({,})结束,自动变量就会自动销毁.因此,名称自动开始.

您的代码示例有什么问题?

所以,您的代码具有未定义的行为.

在您的示例范围内,*p它是创建后的整个函数体.
但是,它x是一个非静态的本地/自动变量,因此一旦范围结束不存在x,它的范围就是结束的生命周期,即}创建它的结束括号x.*p指向不再存在的东西.

请注意,技术上x不存在超出其范围,但是可能发生编译器没有删除内容,x并且可能x通过指针访问超出其范围的内容(如您所做).但是,执行此操作的代码不是有效的C++代码.它是一个调用Undefined Behavior的代码.这意味着任何事情都可能发生(你甚至可能看到x完整的价值),并且不应该期望这样的代码可观察到的行为.

  • 请注意,本地(块范围)变量不一定具有自动生存期.您也可以将它们定义为静态.在这种情况下,它们具有静态生命周期. (3认同)
  • @ user695652:它由编译器生成的代码进行管理。作用域和生存期规则在C ++标准中已得到很好的定义,并且编译器会执行这些规则。 (2认同)

pho*_*xis 8

C11第6.2.1节第2段

对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本的区域内可见(即,可以使用).由相同标识符指定的不同实体具有不同的范围,或者在不同的名称空间中

.

C11第6.2.4节第2段

对象的生命周期是程序执行的一部分,在此期间保证为其保留存储.

在你的情况下x是块的本地,它的生命周期也是如此,因此x不能通过它在块外的名称访问,也因为它的生命周期限于它的块x,在离开块之后不再保留地址,因此将导致未定义的行为.

另一方面,例如,假设一个static局部变量,在这种情况下,范围是块的本地,因此我们不能通过其名称访问块外,但生命周期是整个程序,所以我们可以使用程序运行时任何位置的变量地址.这个例子应该有助于发挥作用.

  • 静态的好例子. (3认同)
  • C 标准中的那些引用对于 C++ 来说是不准确的。某些类型的对象的生命周期可能在保证为它们分配存储之后的某个时间点开始,并在其存储被回收之前的某个时间点结束。 (2认同)

Oli*_*rth 7

对象(即存储值的实际底层事物)具有生命周期.

变量(即用于引用对象的东西)具有范围.

无论哪种方式,都会y = *p调用未定义的行为; 引用的对象x自动的,它的生命周期在x超出范围时结束.

  • 说真的,*names* 有作用域,是用来指代对象的东西。根据定义,变量是命名对象或引用,因此“变量”一词在您的工具包中提供了一个额外的工具,如果您的工作是试图让人们混淆对象和名称之间的区别;-) 考虑例如 3.2/ 1 “名称出现的变量...”作为使用“变量”并明确表示对象的标准示例,而不是用于指代对象的事物。 (2认同)