2012-01-17 103 views
0

這樣的事情會發生什麼?當你多次聲明同一個對象/變量時會發生什麼(新手)

static int i; 

// wrapped in a big loop 
void update_text() 
{ 
    std::stringstream ss; // this gets called again and again 
    ++i; 
    ss << i; 
    text = new_text(ss.str()); // text and new_text are defined elsewhere 
    show_text(text); // so is this 
} 

確實是在堆棧中用新地址和所有東西創建一個新的ss實例?用char數組使用sprintf會更聰明嗎?

回答

6

每次調用該函數時,一個新的本地實例std::stringstream ss被壓入堆棧。在函數結束時,這個實例被銷燬並從堆棧中彈出。

功能update_text的功能範圍沒有任何時間點在其範圍內具有多個變量,其標識符爲ss。因此,在update_text的範圍內,只有一個ss標識符。

字符數組沒有區別。每次調用該函數時,如果靜態分配,char數組將被推入堆棧並在結束時彈出。如果使用動態內存並動態分配字符數組,則每次調用該函數時仍會執行newdelete語句,並且指向該字符數組的指針仍將被推入並彈出堆棧。 std::stringstream已在內部爲您處理newdelete

聲明一個對象多次是這樣的:

void Function() 
{ 
    int x; 
    int x; 
} 

這將導致編譯器錯誤。

被警告,不過,這是有效的:

void Function() 
{ 
    int x; 
    if(true) 
    { 
     int x; 
    } 
} 

因爲這兩個變量是不同的範圍的。第二個x只存在於if聲明中。因此,編譯器可以推斷在該聲明之後並且在該範圍內對x的任何引用是指第二個x。請注意,類型無關緊要,它是重要的標識符或「名稱」。

0

小問題:你的問題不是關於多次聲明一個對象,而是遇到一個對象初始化多次的位置。

所以要回答你真正的問題:是的,它會在每次調用函數時創建新的ss實例(儘管如果從循環中調用它,地址實際上是相同的,但實際上不應該對程序員來說很重要)。

對於第二個問題:使用sprintf和char數組會更聰明嗎?那麼如果你是新手C++的話,你應該從中得到的答案是否定的,因爲sprintf對於使用streams(缺少類型安全,溢出風險)更危險。實際的答案將取決於。如果您知道自己在做什麼,並且使用stringstreams的性能不足以達到您的目的(這種情況很少發生),請使用sprintf。此外請注意,您可以重複使用stringstreams,這可以減少每次創建新內容的開銷(這對於流式傳輸單個int非常重要),您還可以查看Boost.Lexical_Cast進行這種類型的投射。根據他們的the performance section of there documentation,它應該像sprintf一樣快,如intstring(沒有自己測試過,所以沒有保證),而不暴露sprintf缺少類型安全性(和bufferoverflows的風險)。 C++ 11也有std::to_string,它可以在不放棄安全性的情況下進行轉換(但是它比boost :: lexical_cast`要靈活得多)。

+0

當創建ss的新實例時,它是否使用新的內存或空間? – john

+0

@john:a)你爲什麼要關心? b)它將被放置在函數被調用的堆棧地址對應的堆棧地址處,這可以與先前的實例相同(但不一定是)。它會在創建時在堆上分配它的內部緩衝區,所以每次調用函數時都會分配內部緩衝區,但是無論內存系統是否決定給它相同的內存塊,都是任何人猜測的。所以每次都會創建它,但它可能會重用內存(或者不關心,誰在乎)。 – Grizzly

相關問題