據我所知,在回圈內宣告變數的效率低于在外部宣告并在回圈內修改它。
例子:
std::list<<double> l;
for(int i = 0; i < 100000; i)
{
double a;
a = 500.0 * i;
l.append(a);
}
另一個帶指標的例子:
std::list<<double *> l;
for(int i = 0; i < 100000; i)
{
double* a;
*a = 500.0 * i;
l.append(a);
}
這些示例沒有足夠的意義,但我只想表明在回圈內宣告了雙精度和指標。
問題是,變數的作用域和回圈是一樣的,所以當回圈進行迭代時,它會破壞變數然后再次宣告它嗎?或者它只是停留在堆中直到for回圈結束?這樣做的效率如何?是不是很浪費資源?
我像在 C 中一樣對其進行編碼。
提前致謝!
uj5u.com熱心網友回復:
在記憶體使用方面,大多數實作沒有區別。通常創建堆疊幀以容納函式內任何位置宣告的所有變數。
但是,如果該型別具有建構式和/或解構式,則在每次回圈迭代時呼叫它可能會產生額外的開銷。如果該型別分配它自己的記憶體(例如std::vector),那么這些分配和釋放也將在每次回圈迭代時發生,而不是只發生一次。
也就是說,如果不需要超過一次迭代,您仍然應該從在回圈內宣告變數開始!很容易忘記清除任何以前的值,這會很快導致錯誤。最好先讓它正確,然后再優化。
uj5u.com熱心網友回復:
作為一般規則,我會說盡可能推遲變數定義。它將幫助您擁有干凈的代碼和更高效的程式。
但是還是回圈的情況下,故事有點不同。假設我們有兩個這樣的回圈:
// loop 1 - define variable outside the loop
MyType t;
for(auto x : x_container)
{
t = DoSthAndGetT(x);
// the rest of the code
}
// loop 2 - define variable inside the loop
for(auto x : x_container)
{
MyType t(DoSthAndGetT(x));
// the rest of the code
}
對于回圈 1,您需要呼叫一個建構式、一個解構式和 n 個賦值。對于回圈 2,您有 n 個建構式和 n 個解構式
因此,考慮到建構式、解構式和賦值的繁重,您可以決定選擇的方法。
uj5u.com熱心網友回復:
首先
double* a;
*a = 500.0 * i;
是完全錯誤的。它呼叫未定義的行為,因為a它沒有指向double. 不要寫這樣的代碼。不要指望指標會變魔術。指標指向某個地方,這就是他們所做的。要存盤 adouble你需要一個double,而不僅僅是一個指標。
不要害怕double在回圈中引入一個臨時的。一個好的編譯器會注意到,無論您是像以前那樣撰寫代碼還是代碼是這樣的,最終結果都絕對沒有區別:
std::list<double> l;
for(int i = 0; i < 100000; i)
{
l.append(500.0 * i);
}
因此,我希望編譯器為三個版本中的任何一個發出相同的輸出。請參閱“as-if”規則到底是什么?.
為了清晰和可讀性,您應該撰寫代碼。
您想a在每個迭代器中使用相同的,還是希望a在每次迭代中使用不同的?這就是決定a在回圈內部或外部宣告的原因。即使在回圈之外宣告它,您也可以引入一個范圍以將范圍限制a為盡可能窄:
std::list<double> l;
{
double a = 0.0;
for (int i = 0; i <100000; i) {
l.append(a);
a = 500.0;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506461.html
