[英]C++ - Array of pointers to object, what is stored in STACK and what in HEAP?
[英]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
本身只是一個指針; 它沒有任何意義。 您可以使用它指向堆棧或堆上的對象,或者根本不指向任何內容。
在類或結構中聲明變量是不同的 - 那些實例化類或結構的地方。
要在堆上創建內容,可以使用new
或std::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;
}
上面的代碼存儲了駐留在堆棧上的指針的地址(並且也泄漏了內存,因為它沒有釋放Object
的已分配內存和delete
)。
由於退出函數后指針被“銷毀”(即它的內存可用於程序所需的任何內容),因此您無法再安全地訪問它 。
上述程序可以:正常運行,崩潰或給你不同的結果。 訪問釋放或釋放的內存稱為未定義的行為 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.