假設我們有一個循環迭代很多次:在循環體內聲明一個變量是否有缺點?
for (int i=0; i < 1000000; ++i) {
int s = 100;
s += i;
cout << s;
}
我們只使用s
循環體裏面,所以我們非常希望有聲明它,所以它不會污染封閉命名空間。
我想知道是否有任何缺點。例如,它是否會產生性能成本,因爲程序在每次迭代中重新聲明s
?
假設我們有一個循環迭代很多次:在循環體內聲明一個變量是否有缺點?
for (int i=0; i < 1000000; ++i) {
int s = 100;
s += i;
cout << s;
}
我們只使用s
循環體裏面,所以我們非常希望有聲明它,所以它不會污染封閉命名空間。
我想知道是否有任何缺點。例如,它是否會產生性能成本,因爲程序在每次迭代中重新聲明s
?
從概念上說該變量在每次迭代時被構造和破壞。
但它會影響性能嗎?那麼,你可以檢查你的情況right here。在第7行刪除int
以在循環局部變量和函數局部變量之間切換。
結論:沒有什麼區別。大會是一樣的!
所以,只要使用你的代碼中有意義的東西。如果您每次迭代需要一個對象,請爲每個對象創建一個對象。優化器比你想象的更聰明。如果這還不夠,你會回到它的數據分析和仔細調整,而不是寬泛的指導方針。
輝煌。因此從概念上講,它是不同的,理論上講,它可能會導致性能損失,但實際上,現代編譯器應該能夠優化這一點。 –
@DunPeal。即使在看過相當多的C++之後,我仍然經常被編譯器從其帽子中優化出來。儘可能使用'const'並調整優化級別,您將看到奇蹟。 – Quentin
是的。在循環中聲明一個變量將導致它在每次迭代時被解構和重構。對於小循環和簡單的數據類型,編譯器可以優化,但是在使用複雜對象和大循環時,最好在外部聲明變量。
如果循環的變量使用太多的內存,則可以將循環和聲明放在大括號中,這樣會在退出後刪除大括號內分配的所有變量。大多數情況下,這種微觀優化並不重要,但如果您使用複雜的類等,只需使用外部初始化變量並每次重置即可。
一般來說,聲明太多變量並不是一個好主意,它會讓你的代碼難以閱讀並增加內存使用量。如果可以的話,不要在不需要時聲明變量。例如,您的示例可以簡化爲for(int i = 0;i<1000000;i++)cout<<i+100;
。如果這樣的優化是可能的並且他們不會讓你的代碼難以閱讀,那就使用它們。
銷燬int是一個noop。變量不再存在,但不需要運行代碼。
不存在的變量的引用或指針具有未定義的行爲。在初始化之前,新創建的局部變量具有未定義的狀態。因此,簡單地重新使用舊變量是合法的,編譯器不必證明沒有這樣突出的引用。
在這種情況下,如果它可以證明值是恆定的100
,它甚至可以跳過除第一次初始化之外的所有內容。它可以「儘早」進行初始化,因爲沒有明確的方法可以及早發現它。在這種情況下,這很容易,大多數編譯器都可以輕鬆完成。在更復雜的情況下,更少。如果將它標記爲const
,編譯器不再需要證明它是未修改的,而是可以假定它!
爲了使某些優化變得簡單,C++中的許多未定義區域都存在。
現在,如果你有更復雜的東西,比如vector<int>{1,2,3,4,5}
,破壞和創造就會變得不那麼簡單。將變量從循環中提取出來仍然是可能的,但對編譯器來說則更加困難。這是因爲動態分配有時難以優化。
是的每一次迭代它將被構建和銷燬 – deW1
@ deW1:謝謝,我在我的問題中修復了它。我不打算讓它成爲UB。 –
@ deW1雖然對於簡單的類型,但我有興趣聽到關於編譯器如何優化的權威答案。 – jwimberley