那些常量數組是否在內存中分配空間或者編譯器是否足夠聰明並將其衰減爲文字?C++編譯器如何處理const數組
我只想在這裏提供一個例子:
const int array[] = {
1, 2, 3, 4, 5
};
嗯,我只是想知道而已。
那些常量數組是否在內存中分配空間或者編譯器是否足夠聰明並將其衰減爲文字?C++編譯器如何處理const數組
我只想在這裏提供一個例子:
const int array[] = {
1, 2, 3, 4, 5
};
嗯,我只是想知道而已。
簡短的回答是:這取決於。
長的答覆是:
如果你編譯如下:
const int array[] = {
1, 2, 3, 4, 5
};
int
main()
{
return array[0];
}
您在x86這樣結束了/ Linux操作系統(簡體):
.globl main
main:
movl $1, %eax
ret
所以,是的,它會不會被存儲在任何地方,而會被視爲編譯時評估的常量。
不過,如果你使用它,因爲這:
const int array[] = {
1, 2, 3, 4, 5
};
int
main()
{
return (long)array;
}
它變成:
.globl main
main:
leal _ZL5array(%rip), %eax
ret
.section .rodata
.align 16
_ZL5array:
.long 1
.long 2
.long 3
.long 4
.long 5
它在部分RODATA結束了,因爲你告訴編譯器,你將真正需要它作爲一個數組。
有一個由Qt背後的專家之一Olivier Goffart編寫的excellent blog post about data initialization in C++。
我相信如果他們是static
,他們可以很容易地進行優化。用一些技巧改變它們的值(例如const_cast
)是未定義的行爲,所以編譯器不會在意。無論如何 - 你可以檢查。 gcc -O2 -S temp.c
。
如果數組是全局數組而不是static
,編譯器應該保留它以防其他編譯單元需要它。除非你進行整體程序優化。
優化器其實是非常聰明的生物。例如,下面的代碼:
const int array[] = {1, 2, 3, 4, 5};
void show(int i)
{
printf("%d\n", i);
}
int main(int argc, char * argv[])
{
show(array[0]);
}
將最有可能最終成爲:
void show()
{
printf("%d\n", 1);
}
int main(int argc, char * argv[])
{
show();
}
我猜測,優化器會注意到,這個節目可以很容易地內聯,所以大概的代碼將被連優化進一步:
int main(int argc, char * argv[])
{
printf("%d\n", 1);
}
@ mr5優化器只在產生與源代碼相同的結果時纔會削減代碼。如果您創建的代碼實際上會要求此數組運行,那麼優化器將保持原樣。請注意,我的代碼不需要數組存在。 – Spook
理論上它完全取決於實施。 C++標準定義了你得到的行爲 - 你如何得到它就留給魔法了。
實際上我期待每一個編譯器(這裏的平臺支持,把該數組中一個const段在編譯的時候,並從那裏直接使用它。
由於優化得好,創建的對象「常量」在未來的狀態中,他們的狀態是固定的(標準使其不確定的行爲可以通過任何方式改變它們),數據流分析器會將其考慮在內。從已知位置讀取數組中的值可以並且通常用數字替代
另外,使用頂級const的IIRC默認情況下使對象成爲靜態的,所以除非你使用'extern',否則它在轉換單元中是私有的。它真的(取值是按值內聯),它根本不會被釋放。
大多數編譯器都可以選擇發送程序集/機器代碼輸出,以便檢查特定實現的功能,也可以使用目標文件轉儲器查看數組的存在。
只有鏈接的答案通常是不被接受的;你能總結一下相關信息嗎? –
不,對不起,我有比複製和粘貼文本更有趣的事情。在網頁之間。如果您認爲這是對您的時間的充分利用,請隨時自行展開答案。我應該點擊「社區wiki」按鈕,以便你能夠做到這一點? –
沒關係,我可以編輯你的答案(雖然我不打算;))。這有一個很好的理由,如果這個鏈接在未來出現故障,你的回答對未來的讀者來說實際上是沒有用的...... –