在C ++中,指针在堆栈展开后是否仍然有效?
答案 0 :(得分:2)
这取决于指向对象的存储。如果该对象是堆栈分配的,那么指针肯定会变得无效 - 堆栈展开将正确地破坏对象。如果对象是堆分配的,那么只有在堆栈展开期间有一些RAII变量释放对象时,指针才会变为无效。
答案 1 :(得分:1)
没有。使用堆栈展开在堆栈的未受损部分的作用域中声明的所有变量/指针都将被销毁。
此外,该规则考虑了变量的Storage Type
例如:A static
变量在函数调用之间保留其值,这意味着它在堆栈展开期间不会被销毁。这是因为静态变量不存储在堆栈上,而是存储在BSS或数据段上。
Local variables
(Auto storage type
)将始终被销毁。
堆栈上分配内存的指针在堆栈展开时不会被销毁,因为它们是在Heap上分配而不是堆栈。
要记住的一个重要规则是 NEVER 返回指针或对函数内局部变量的引用。指针或引用将包含垃圾值。
答案 2 :(得分:1)
这取决于指针指向的内容。如果它指向堆内存,它仍然有效。如果它指向堆栈内存,它将变为无效。
答案 3 :(得分:1)
考虑一些例子:
void* f1a()
{
void* p = malloc(10);
return p;
}
...与...相同
void* f1b()
{
return malloc(10);
}
没关系,因为指针指向堆,因此独立于堆栈,函数调用和编程范围。函数返回时复制指针值。
int* f2()
{
int x;
return &x; // pointer to x - about to become invalid!
}
上面返回一个指向堆栈上变量x
的指针,当函数返回时,它将被回收(x
丢失)。
答案 4 :(得分:0)
只是说出一件我认为重要的额外事情
说我们有这个陈述
obj* objptr = new obj(9) //allocate memory on heap and use constructor
如果此处发生异常.. 内存堆被重新传回....即没有内存泄漏......
原因是.... 不是因为堆栈展开...而是因为new运算符转换为以下生成代码的方式 try catch语句在new运算符中实现......类似这样......
void * operator new(size_t s)
{
try
{
void * ptr=new(malloc (s))sample(); //placement new
ptr->...
}
catch(..)
{
operator delete(ptr); //<= notice here so if an exception occur then first it is caught here which releases the memory
}
}
但是如果在对象内部进行了一些内存分配仍然没有被释放..