簡體   English   中英

C++中的變量存儲在哪里?

[英]Where are variables in C++ stored?

C++中的變量存儲在哪里?

在 RAM 或處理器的緩存中?

命名變量存儲:

  • 在堆棧上,如果它們是函數局部變量。
    C++ 稱這種“自動存儲”為1並且不要求它實際上是 asm 調用堆棧,在一些罕見的實現中它不是。 但在主流實現中確實如此。
  • 在每個進程的數據區域中,如果它們是 global 或static
    C++ 稱之為“靜態存儲類”; 它通過在section .data.bss.rodata或類似section .data放置/保留字節在 asm 中實現。

如果變量是一個用int *p = new int[10];初始化的指針int *p = new int[10]; 或類似的,指針變量p將進入自動存儲或靜態存儲,如上所述。 內存中指向的對象是:

  • 在堆上(C++ 稱之為動態存儲),用newmalloc等分配。
    在 asm 中,這意味着調用分配器函數,如果其空閑列表為空,則該函數最終可能會通過某種系統調用從操作系統獲取新內存。 “堆”不是現代操作系統/C++ 實現中的單個連續區域。

C 和 C++ 不進行自動垃圾收集,命名變量本身不能處於動態存儲(“堆”)中。 動態存儲中的對象是匿名的,除了被其他對象指向之外,其中一些可能是適當的變量。 (結構或類類型的對象,與像int這樣的原始類型相反,可以讓你引用這個匿名對象中的命名類成員。在成員函數中,它們甚至看起來是相同的。)

這就是為什么您不能(安全/有用地)返回指向局部變量的指針或引用的原因。


當然,這一切都在 RAM 中 緩存對用戶空間進程是透明的,盡管它可能會明顯影響性能。

編譯器可以優化代碼以將變量存儲在寄存器中。 這是高度依賴於編譯器和代碼的,但好的編譯器會積極地這樣做。


腳注 1:有趣的事實: auto在 C++03 及更早版本中,並且仍然在 C 中,表示自動 storage-class ,但現在 (C++11) 它推斷類型。

一般來說,對於 C++,正確的答案是“無論你的編譯器決定把它們放在哪里”。 您不應該以其他方式做出假設,除非您以其他方式指導編譯器。 有些變量可以完全存儲在寄存器中,有些變量可能會被完全優化掉並在某處替換為文字。 對於某些平台上的某些編譯器,常量實際上可能最終出現在 ROM 中。

您關於“處理器緩存”的問題的一部分有點困惑。 有一些工具可以指導處理器如何處理其緩存,但通常這是處理器的業務,您應該看不到。 您可以將緩存視為 CPU 進入 RAM 的窗口。 幾乎任何內存訪問都通過緩存。

另一方面,在大多數操作系統上,未使用的 RAM 有時會被換出到磁盤。 因此,在某些時候您的變量實際上可能(但不太可能)存儲在磁盤上。 :-)

變量通常存儲在 RAM 中。 這是在堆上(例如全局變量、方法/函數中的靜態變量)或堆棧上(例如在方法/函數中聲明的非靜態變量)。 堆棧和堆都是 RAM,只是位置不同。

指針有點特殊。 指針本身遵循上述規則,但它們指向的數據通常存儲在堆上(用malloc創建的內存塊,用new創建的對象)。 但是您可以創建指向堆棧內存的指針: int a = 10; int * b = &a; int a = 10; int * b = &a; ; b指向的存儲器aa被存儲在堆棧中。

進入 CPU 緩存的內容超出了編譯器的控制,CPU 自行決定緩存什么以及緩存它的時間長短(取決於諸如“此數據最近是否被使用過? ”或“是否預期使用該數據?很快又回來了? ”)當然緩存的大小也有很大的影響。

編譯器只能決定哪些數據進入 CPU 寄存器。 如果連續頻繁訪問數據,通常數據會保存在那里,因為寄存器訪問速度比緩存快,比 RAM 快得多。 某些系統上的某些操作實際上只能在數據位於寄存器中時才能執行,在這種情況下,編譯器必須在執行操作之前將數據移至寄存器,並且只能決定何時將數據移回 RAM。

編譯器將始終嘗試將最常訪問的數據保存在寄存器中。 當一個方法/函數被調用時,通常所有的寄存器值都會被寫回 RAM,除非編譯器可以確定被調用的函數/方法不會訪問數據來自的內存。 同樣在方法/函數返回時,它必須將所有寄存器數據寫回 RAM,否則新值將丟失。 在某些 CPU 架構上,返回值本身在寄存器中傳遞,否則通過堆棧傳遞。

C++ 中的變量存儲在堆棧或堆中。

堆:

int x;

堆:

int *p = new int;

話雖如此,兩者都是內置於 RAM 中的結構。

如果您的 RAM 使用率很高,盡管 Windows 可以將其交換到磁盤。

當對變量進行計算時,內存將被復制到寄存器。

C++ 不知道您的處理器的緩存。

當您運行用 C++ 或任何其他語言編寫的程序時,您的 CPU 將在緩存中保留一份“流行”RAM 塊的副本。 這是在硬件級別完成的。

不要將 CPU 緩存視為“其他”或“更多”內存……它只是一種將一些 RAM 塊保持在附近的機制。

我認為您混淆了兩個概念。 一、C++語言如何在內存中存儲變量。 二,計算機和操作系統如何管理該內存。

在 C++ 中,變量可以在堆棧上分配,堆棧是為程序使用而保留的內存,在線程啟動時大小固定,或者在動態內存中,可以使用 new 動態分配。 如果代碼分析允許,編譯器還可以選擇將變量存儲在處理器的寄存器中。 這些變量永遠不會看到系統內存。

如果變量在內存中結束,操作系統和處理器芯片組接管。 基於堆棧的地址和動態地址都是虛擬的。 這意味着它們可能會或可能不會在任何給定時間駐留在系統內存中。 in memory 變量可以存儲在系統內存中,分頁到磁盤上,或者可以駐留在處理器上或附近的緩存中。 因此,很難知道這些數據實際上在哪里。 如果一個程序有一段時間沒有空閑或兩個程序正在爭奪內存資源,則可以將該值保存在頁面文件中的磁盤中,並在程序運行時恢復。 如果該變量是正在完成的某些工作的本地變量,則可以在處理器緩存中對其進行多次修改,然后最終將其刷新回系統內存。 您編寫的代碼永遠不會知道發生了這種情況。 它只知道它有一個地址可以操作,所有其他系統負責其余的工作。

C++ 語言支持通過 C++ 程序中的變量進行兩種內存分配:

靜態分配是當您聲明靜態或全局變量時發生的情況。 每個靜態或全局變量定義一個固定大小的空間塊。 該空間在您的程序啟動時(exec 操作的一部分)分配一次,並且永遠不會被釋放。 當您聲明一個自動變量(例如函數參數或局部變量)時,就會發生自動分配。 自動變量的空間在包含聲明的復合語句進入時分配,並在復合語句退出時釋放。 自動存儲的大小可以是變化的表達式。 在其他 CPP 實現中,它必須是一個常量。 C++ 變量不支持第三種重要的內存分配,動態分配,但可用的庫函數。 動態內存分配

動態內存分配是一種技術,其中程序在運行時確定存儲某些信息的位置。 當您需要的內存量或您繼續需要多長時間取決於程序運行之前未知的因素時,您需要動態分配。

例如,您可能需要一個塊來存儲從輸入文件中讀取的行; 由於對一行的長度沒有限制,因此您必須動態分配內存並在您閱讀更多行時動態地使其變大。

或者,您可能需要為輸入數據中的每個記錄或每個定義一個塊; 由於您無法預先知道會有多少,您必須在閱讀時為每個記錄或定義分配一個新塊。

使用動態分配時,內存塊的分配是程序顯式請求的操作。 當您想分配空間時調用函數或宏,並用參數指定大小。 如果你想釋放空間,你可以通過調用另一個函數或宏來實現。 你可以隨時隨地做這些事情。

CPP 變量不支持動態分配; 沒有“動態”存儲類,永遠不可能有一個 CPP 變量的值存儲在動態分配的空間中。 獲得動態分配內存的唯一方法是通過系統調用,而引用動態分配空間的唯一方法是通過指針。 因為不太方便,而且動態分配的實際過程需要更多的計算時間,所以程序員一般只有在靜態分配和自動分配都不會服務的情況下才使用動態分配。

例如,如果要動態分配一些空間來保存結構體 foobar,則不能聲明內容為動態分配空間的結構體 foobar 類型的變量。 但是您可以聲明一個指針類型的變量 struct foobar * 並為其分配空間的地址。 然后你可以在這個指針變量上使用運算符 '*' 和 '->' 來引用空間的內容:

 {
   struct foobar *ptr
      = (struct foobar *) malloc (sizeof (struct foobar));
   ptr->name = x;
   ptr->next = current_foobar;
   current_foobar = ptr;
 }

變量可以保存在許多不同的地方,有時在多個地方。 加載程序時,大多數變量都放在 RAM 中; 有時聲明為const變量被放置在 ROM 中。 每當訪問變量時,如果它不在處理器的高速緩存中,就會導致高速緩存未命中,並且處理器將在變量從 RAM/ROM 復制到高速緩存時停頓。

如果您有任何不錯的優化編譯器,則局部變量通常會存儲在處理器的寄存器文件中。 變量將在讀取和寫入時在 RAM、緩存和寄存器文件之間來回移動,但它們通常始終在 RAM/ROM 中具有副本,除非編譯器決定不需要這樣做。

根據它們的聲明方式,它們將存儲在“”或“堆棧”中

堆是應用程序可以使用的動態數據結構。

當應用程序使用數據時,必須在它們被消耗之前將其移動到 CPU 的寄存器,但是這是非常易失的臨時存儲。

暫無
暫無

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

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