是否可以使用指向“if”语句中声明的变量的地址的指针

时间:2017-02-09 05:27:53

标签: c++ pointers variables if-statement memory-address

是否可以使用指向“if”语句中声明的变量地址的指针? 示例如下:

...
int *pTest = 0;
if (...)
{
  int x = 10;
  pTest = &x;
}
else
{
  int x = 100;
  pTest = &x;
}
...
// use pTest 

4 个答案:

答案 0 :(得分:6)

问题是指针的寿命大于指向的对象的寿命。这闻起来很糟糕,你应该重新考虑你想要做的事情。

答案 1 :(得分:2)

简短的回答是使用该指针是不安全的。答案很长很复杂。如果您以非常具体的方式执行此操作,可以这样做,老实说,我认为您不应该这样做。指针pTest将在所有可能性中指向相对于堆栈指针的位置。只要没有其他任何位置,你可以安全地使用它。这就是为什么它可以"工作"在某些情况下。也就是说,这里有一些可能导致失败的事情:

  1. 另一个变量可能占用相同的空间,因为一旦该变量超出范围,另一个变量可能会占用相同的空间。这与使用已释放的内存类似。
  2. 编译器可能会对您的代码进行转换,并假设它不依赖于未定义的行为(这是)。例如,这可以表明编译器只是优化了这一行:

    pTest = &x;

  3. 编译器可能优化该特定行的原因是它得出结论,任何依赖于从那里读取指针的代码依赖于未定义的行为,因此(理想情况下)程序员知道这一点并且不会编写依赖于未定义行为的代码。然后,优化器将得出结论,最有效的解决方案是什么都没有。这不会破坏任何不依赖于未定义行为的代码。

答案 2 :(得分:2)

更新:我找到了this relevant question。由于那里的标准引用,我可以说确实有一个段落导致指针值在对象的生命周期结束时变为无效。此外,对具有无效值的指针执行左值到右值转换是实现定义的行为。

因此,我的下面答案应该最终改为实现定义。这意味着您需要执行此实现来记录执行此左值到右值转换时将执行的操作,如果这对您很重要。

旧答案

如果您的使用定义意味着左值到右值的转换(例如,打印值,将值复制到另一个指针,而不是取消引用它),我相信标准是可以的。

  

[cov.lval] / 3.3-3.4:

     
    
        
  • 否则,如果glvalue引用的对象包含无效的指针值([basic.stc.dynamic.deallocation],     [basic.stc.dynamic.safety]),行为是实现定义的。

  •     
  • 否则,glvalue指示的对象中包含的值是prvalue结果。

  •     
  
     

[basic.stc.dynamic.safety] / 4:

     
    

实现可能放松了指针安全性,在这种情况下,指针值的有效性不取决于它是否为a     安全派生的指针值。或者,实现可以     有严格的指针安全性,在这种情况下指针值指的是     动态存储持续时间不是安全派生的对象     除非引用,否则指针值是无效的指针值     之前已声明完整对象可以访问     ([util.dynamic.safety])。

  

因此,如果我们有严格的指针安全性,它仍然有效 - 这件事不会使它无效,因为它没有引用具有动态存储持续时间的对象。

简而言之,我声称在左值到右值的转换中使用它是安全的。如果标准中有另一个段落使其值无效,因为所引用的对象不再存在,或者“glvalue指示的对象中包含的值”存在一些模糊的问题,我很乐意看到它。

¹:在这个一般领域here进行了一些很好的讨论。我简化了这一部分,因为*p的大多数用法都是未定义的行为。

答案 3 :(得分:0)

如果你使用“new”为变量x分配内存并指向它的指针,那就没问题了。因为当变量x的作用域结束时(如果是if),x的VALUE仍将保留在堆上(分配给程序的动态内存),并且指针仍将指向某个有效值。但在你的情况下,因为分配给变量x的内存没有动态分配,所以一旦x的范围结束于if的块之外,x的VALUE也会消失,所以在这种情况下指针现在不指向变量的值而是它现在指向一些垃圾值