编辑:关于为什么此问题中的代码有效的问题已通过重复标记中的链接问题得到解答.关于字符串文字生命周期的问题在这个问题的答案中得到了回答.
我试图了解如何以及何时const char *取消分配指向的字符串.
考虑:
const char **p = nullptr;
{
const char *t = "test";
p = &t;
}
cout << *p;
Run Code Online (Sandbox Code Playgroud)
离开内部范围后,我希望p是一个悬垂的指针const char *.但是在我的测试中并非如此.这意味着t即使在t超出范围之后,实际值仍然有效且可访问.
这可能是由于通过将它绑定到const引用来延长临时的生命周期.但我不做这样的事情,甚至通过t在成员变量中保存引用并从以后打印不同函数的值仍然给我正确的值.
class CStringTest
{
public:
void test1()
{
const char *t = "test";
m_P = &t;
test2();
}
void test2()
{
cout << *m_P;
}
private:
const char **m_P = nullptr;
};
Run Code Online (Sandbox Code Playgroud)
那么t这里价值的生命周期是多少?我会说我通过取消引用指向超出范围的变量值的指针来调用未定义的行为.但它每次都有效,所以我认为情况并非如此.
尝试其他类型的时候QString:
QString *p = nullptr;
{
QString str = "test";
p = &str;
}
cout << *p;
Run Code Online (Sandbox Code Playgroud)
代码总是正确地打印值,即使它不应该.str超出了它的值范围,我没有通过将它绑定到const引用来延长它的生命周期.
有趣的是,类示例的QString行为与我期望的一样,并test2()打印出乱码,因为该值确实超出了范围并m_P成为悬空指针.
那么实际的生命周期是const char *多少?
变量p和t您声明的堆栈变量,因此它们的生命周期在其封闭块的末尾结束.
但是值t是字符串文字的地址"test",而不是你声明的变量,它不在堆栈上.它是一个字符串文字,它是程序中定义的常量(类似于整数字面值99或浮点字面值0.99).文字不出去的范围,因为你期望的,因为他们不产生或破坏,他们只是有.
标准说:
评估字符串文字会产生具有静态存储持续时间的字符串文字对象,从上面指定的给定字符初始化.
因此,编译器创建的用于表示文字的对象"test"具有静态存储持续时间,该持续时间与全局变量和static变量的持续时间相同,这意味着它不会像堆栈变量一样超出范围.
值p的地址是t,当超出范围时,它确实成为无效指针t,但这并不意味着存储在该地址的值突然变得不可访问或被擦除.表达式*p是未定义的行为,但它似乎工作,因为没有任何东西重用该内存位置,所以*p仍然包含字符串文字的地址.有关详细信息,请参阅顶部答案可以在其范围之外访问局部变量的内存吗?
| 归档时间: |
|
| 查看次数: |
2379 次 |
| 最近记录: |