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



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

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

问题是指针的寿命比所指向对象的寿命长。这闻起来很难闻,你应该重新思考你想做什么。

简单的答案是使用该指针是不安全的。答案比较复杂。如果你以一种非常具体的方式这样做,你可以,老实说,我认为你永远都不应该这样做。指针pTest很可能指向一个相对于堆栈指针的位置。只要没有其他东西破坏这个位置,你就可以安全地使用它;工作;在某些情况下。也就是说,以下是一些可能导致失败的因素:

  1. 另一个变量可能会占用相同的空间,因为一旦该变量超出范围,另一变量可能会占据相同的空间。这类似于使用已释放的内存。

  2. 编译器可能会对代码进行转换,假设它不依赖于未定义的行为(事实就是这样)。例如,这可能表明编译器只是优化了这一行:

    pTest = &x;

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

UPDATE:我发现了这个相关的问题。多亏了其中的标准引用,我可以说,当对象的生命周期结束时,确实有一段导致指针值无效。此外,对具有无效值的指针执行左值到右值的转换是实现定义的行为。

因此,我下面的答案最终应该改为实现定义。这意味着,如果这对您很重要的话,您的实现需要记录它在执行这种左值到右值转换时会做什么。


旧答案

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

[cov.lval]/3.3-3.4:

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

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

[基本.stc.动态.安全]/4:

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

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

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


:这里有一些关于这一领域的精彩讨论。我简化了这一部分,因为*p的大多数使用都是未定义的行为。

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

最新更新