C ++中的指针存储在堆栈中还是堆中?

时间:2014-06-24 07:37:45

标签: c++ pointers memory-management

我试图理解堆栈内存之间的区别,并且SO上的this question以及this explanation做得很漂亮很好地解释了基础知识。

然而,在第二个解释中,我遇到了一个我有一个具体问题的例子,例子如下:

heap allocation example

有人解释说对象m是在上分配的,我只是想知道这是不是完整的故事。根据我的理解,对象本身确实是在上分配的,因为new关键字已用于其实例化。

但是,指向对象m的指针是否在堆栈上分配的同一时间?否则,如何访问对象本身,当然它位于中。我觉得为了完整起见,本教程中应该提到这一点,留下它会给我带来一些混乱,所以我希望有人能够清楚地告诉我,我对我的理解是正确的基本上应该有两个陈述:

1。指向对象m的指针已在堆栈上分配

2。对象m本身(因此它携带的数据以及对其方法的访问权限)已在堆上分配

4 个答案:

答案 0 :(得分:17)

您的理解可能是正确的,但陈述是错误的:

  

已经在堆栈上分配了指向对象m的指针。

m 指针。它在堆栈上。也许你的意思是指向Member对象的指针

  

对象m本身(它携带的数据以及对其方法的访问权限)已在堆上分配。

正确就是说 m指向的对象是在堆上创建的

通常,在堆栈上创建任何函数/方法本地对象和函数参数。由于m函数本地对象,因此它位于堆栈上,但m指向的对象位于堆上。

答案 1 :(得分:14)

"堆"和"堆"通用编程术语。特别是,不需要通过堆栈或堆数据结构在内部管理存储。

C ++具有以下存储类

  • 静态
  • 自动
  • 动态
  • 螺纹

粗略地说, dynamic 对应于" heap",而自动对应于" stack"。

转到你的问题:可以在这四个存储类中的任何一个中创建指针;和指向的对象也可以在任何这些存储类中。一些例子:

void func()
{
    int *p = new int;            // automatic pointer to dynamic object
    int q;                       // automatic object
    int *r = &q;                 // automatic pointer to automatic object
    static int *s = p;           // static pointer to dynamic object
    static int *s = r;           // static pointer to automatic object (bad idea)
    thread_local int **t = &s;   // thread pointer to static object 
}

在没有说明符的情况下声明的命名变量在函数中是自动,否则是 static

答案 2 :(得分:5)

在函数中声明变量时,它总是在堆栈上。因此,您的变量Member* m将在堆栈上创建。请注意,m本身只是一个指针;它并没有指向任何东西。您可以使用它指向堆栈或堆上的对象,或者根本不指向任何内容。

声明类或结构中的变量是不同的 - 那些实例化类或结构的地方。

要在堆上创建内容,请使用newstd::malloc(或其变体)。在您的示例中,使用new在堆上创建对象,并将其地址分配给m。需要释放堆上的对象以避免内存泄漏。如果使用new分配,则需要使用delete;如果使用std::malloc分配,则需要使用std::free。更好的方法通常是使用"智能指针",这是一个包含指针的对象,并有一个析构函数可以释放它。

答案 3 :(得分:2)

是的,指针在堆栈上分配,但指针指向的对象在堆上分配。你是对的。

  

但是,指向对象m的指针不是同时发生的   在堆栈上分配?

我想你的意思是Member对象。指针在堆栈上分配,并在函数(或其范围)的整个持续时间内持续存在。之后,代码可能仍然有效:

#include <iostream>
using namespace std;

struct Object {
    int somedata;
};

Object** globalPtrToPtr; // This is into another area called 
                         // "data segment", could be heap or stack

void function() {
    Object* pointerOnTheStack = new Object;
    globalPtrToPtr = &pointerOnTheStack;
    cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
} // pointerOnTheStack is NO LONGER valid after the function exits

int main() {
     // This can give an access violation,
     // a different value after the pointer destruction
     // or even the same value as before, randomly - Undefined Behavior
    cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
    return 0;
}

http://ideone.com/BwUVgm

上面的代码存储了驻留在堆栈上的指针的地址(并且因为它没有Object分配的内存delete而泄漏内存。“ / p>

由于在退出函数后,指针被&#34;销毁&#34; (即,它的内存可以用于程序中的任何内容),您无法再安全地访问它

上述程序可以:正常运行,崩溃或给您不同的结果。访问释放或取消分配的内存称为未定义的行为