簡體   English   中英

C ++中的指針存儲在堆棧中還是堆中?

[英]Where are pointers in C++ stored, on the stack or in the heap?

我試圖理解堆棧內存之間的區別, 這個問題在SO上以及這個解釋做了很好的解釋基礎知識。

然而,在第二個解釋中,我遇到了一個我有一個具體問題的例子,例子如下:

堆分配示例

解釋說對象m是在堆上分配的,我只是想知道這是不是完整的故事。 根據我的理解,對象本身確實在堆上分配,因為new關鍵字已用於其實例化。

但是, 指向對象m的指針是否在堆棧上分配的同一時間 否則,如何訪問對象本身,當然它位於堆中 我覺得為了完整起見,本教程中應該提到這一點,留下它會給我帶來一些混亂,所以我希望有人能夠清楚地告訴我,我對我的理解是正確的應該基本上有兩個陳述,不得不說:

1.已經在堆棧上分配了指向對象m的指針

2.對象m本身(因此它攜帶的數據以及對其方法的訪問)已在堆上分配

您的理解可能是正確的,但陳述是錯誤的:

已經在堆棧上分配了指向對象m的指針。

m 指針。 它在堆棧上。 也許你的意思是指向一個Member對象

對象m本身(它攜帶的數據以及對其方法的訪問)已在堆上分配。

正確的是m指向的對象是在堆上創建的

通常,在堆棧上創建任何函數/方法本地對象和函數參數。 由於m函數本地對象,因此它位於堆棧上,但m指向的對象位於堆上。

“堆棧”和“堆”是通用編程術語。 特別是,不需要通過堆棧或堆數據結構在內部管理存儲。

C ++具有以下存儲類

  • 靜態的
  • 自動
  • 動態

粗略地, 動態對應於“堆”,而自動對應於“堆棧”。

轉到你的問題:可以在這四個存儲類中的任何一個中創建指針; 和指向的對象也可以在任何這些存儲類中。 一些例子:

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 
}

如果在函數內,則聲明沒有說明符的命名變量是自動的 ,否則是靜態的

在函數中聲明變量時,它總是在堆棧上。 所以你的變量Member* m是在堆棧上創建的。 注意, m本身只是一個指針; 它沒有任何意義。 您可以使用它指向堆棧或堆上的對象,或者根本不指向任何內容。

在類或結構中聲明變量是不同的 - 那些實例化類或結構的地方。

要在堆上創建內容,可以使用newstd::malloc (或它們的變體)。 在您的示例中,使用new在堆上創建對象並將其地址分配給m 需要釋放堆上的對象以避免內存泄漏。 如果使用new分配,則需要使用delete ; 如果使用std::malloc分配,則需要使用std::free 更好的方法通常是使用“智能指針”,它是一個包含指針的對象,並具有釋放它的析構函數。

是的,指針在堆棧上分配,但指針指向的對象在堆上分配。 你說的沒錯。

但是,指向對象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 )。

由於退出函數后指針被“銷毀”(即它的內存可用於程序所需的任何內容),因此您無法再安全地訪問它

上述程序可以:正常運行,崩潰或給你不同的結果。 訪問釋放或釋放的內存稱為未定義的行為

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM