簡體   English   中英

堆棧框架問題:Java 與 C++

[英]Stack Frame Question: Java vs C++

一季度。 在Java中,所有的對象、數組和類變量都存儲在堆上? C++ 也是如此嗎? 數據段是堆的一部分嗎?

下面的 C++ 代碼怎么樣?

class MyClass{
    private:
            static int counter; 
            static int number;
};

MyClass::number = 100;

Q2。 就我的理解,編譯器賦予特定值的變量存儲在數據段中,未初始化的全局和靜態變量存儲在 BSS(由符號開始的塊)中。 在這種情況下,靜態的 MyClass::counter 被編譯器初始化為零,因此它存儲在 BSS 中,而初始化為 100 的 MyClass::number 存儲在數據段中。 我的結論正確嗎?

Q3。 考慮以下代碼:

void doHello(MyClass &localObj){   
// 3.1 localObj is a reference parameter, where will this get stored in Heap or Stack?
      // do something
}

void doHelloAgain(MyClass localObj){   
// 3.2 localObj is a parameter, where will this get stored in Heap or Stack?
      // do something
}

int main(){
      MyClass *a = new MyClass();  // stored in heap

      MyClass localObj;   
      // 3.3 Where is this stored in heap or stack?
      doHello(localObj);
      doHelloAgain(localObj);
}

我希望我已經向所有人說明了我的問題

編輯:

請參考這篇文章對 BSS 有一些了解

EDIT1:將類名從 MyInstance 更改為 MyClass,因為它是一個糟糕的名稱。 誠摯的道歉

EDIT2:將類成員變量編號從非靜態更改為靜態

這有點簡化,但據我所知,大部分都是准確的。

在 Java 中,所有對象都在堆上分配(包括所有成員變量)。 大多數其他東西(參數)是引用,引用本身與本機類型(整數、長整數等)一起存儲在堆棧中,除了字符串,它更像是一個對象而不是本機類型。

在 C++ 中,如果要使用“new”關鍵字分配所有對象,它的情況與 java 幾乎相同,但在 C++ 中有一種獨特的情況,因為您可以改為在堆棧上分配對象(您並不總是必須使用“新”)。

還要注意,Java 的堆性能比 C 的堆性能更接近 C 的堆棧性能,垃圾收集器做了一些非常聰明的事情。 它仍然不如堆棧好,但比堆好得多。 這是必要的,因為 Java 無法在堆棧上分配對象。

第一季度

Java 還在堆棧上存儲變量,但在堆上分配類實例。 在 C++ 中,您可以在堆棧或堆上自由分配類實例。 通過使用new關鍵字,您可以在堆上分配實例。

數據段不是堆的一部分,而是在進程啟動時分配的。 堆用於動態內存分配,而數據段是靜態的並且內容在編譯時是已知的。

BSS 段只是一種優化,其中所有屬於數據段(例如字符串、常量等)的未初始化或初始化為零的數據都移動到 BSS 段。 數據段必須嵌入到可執行文件中,通過將“所有零”移動到末尾,它們可以從可執行文件中刪除。 當加載可執行文件時,BSS 段被分配並初始化為零,編譯器仍然能夠知道 BSS 段內的各種緩沖區、變量等的地址。

Q2

MyClass::number存儲在分配MyClass類的實例的位置。 它可以在堆上,也可以在堆棧上。 注意在 Q3 中a如何指向在堆上分配的MyClass的實例,而localObj是在堆棧上分配的。 因此a->number位於堆上,而localObj.number位於堆棧上。

由於MyClass::number是一個實例變量,您不能像這樣分配它:

MyClass::number = 100;

但是,您可以分配MyClass::counter因為它是靜態的(除了它是私有的):

MyClass::counter = 100;

Q3

當您調用doHello ,變量localObj (在main )是通過引用傳遞的。 變量localObjdoHello指回堆棧變量。 如果您更改它,則更改將存儲在分配main中的localObj的堆棧中。

當您調用doHelloAgain ,變量localObj (在main )被復制到堆棧中。 doHelloAgain內部,變量localObj分配在堆棧上,並且僅在調用期間存在。

一季度。 在Java中,所有的對象、數組和類變量都存儲在堆上? C++ 也是如此嗎? 數據段是堆的一部分嗎?

不,數據部分與堆分開。 基本上,數據部分是在加載時分配的,之后的所有內容都有一個固定的位置。 此外,可以在堆棧上分配對象。

對象位於堆上的唯一時間是使用new關鍵字,或者使用malloc系列函數中的某些內容。

Q2。 就我的理解,編譯器賦予特定值的變量存儲在數據段中,未初始化的全局和靜態變量存儲在 BSS(由符號開始的塊)中。 在這種情況下,靜態的 MyInstance::counter 被編譯器初始化為零,因此它存儲在 BSS 中,而初始化為 100 的 MyInstance::number 存儲在數據段中。 我的結論正確嗎?

是的,您對 BSS 部分的理解是正確的。 但是,由於number不是靜態的代碼:

MyInstance::number = 100;

不合法,它需要在構造函數中正確設置為靜態或初始化。 如果在構造函數中初始化它,它就會存在於分配擁有對象的任何地方。 如果您將其設為靜態,它將最終出現在數據部分......如果在任何地方。 通常static const int變量可以直接內聯到所使用的代碼中,這樣根本不需要全局變量。

Q3。 考慮以下代碼:...

void doHello(MyInstance &localObj){

localObj 是對傳遞對象的引用。 據您所知,沒有存儲,它指的是傳遞的變量在哪里。 實際上,在幕后,可能會在堆棧上傳遞一個指針以促進這一點。 但是如果可以的話,編譯器也可以很容易地優化它。

void doHelloAgain(MyInstance localObj){

傳遞的參數的副本放置在堆棧中。

MyInstance localObj;
// 3.3 Where is this stored in heap or stack?

localObj 在堆棧上。

在 C++ 中,對象可能會在堆棧上分配……例如,Q3 主例程中的 localObj。

我感覺到一些關於類與實例的混淆。 “MyInstance”作為變量名比作為類名更有意義。 在您的 Q1 示例中,“數字”存在於 MyInstance 類型的每個對象中。 “計數器”由所有實例共享。 "MyInstance::counter = 100" 是一個有效的賦值,但 "MyInstance::number = 100" 不是,因為你還沒有指定應該將它的 "number" 成員分配給哪個對象。

此處列出C++ 中的所有內存區域

暫無
暫無

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

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