2012-02-03 156 views
1

開始與代碼:C++是堆棧還是堆分配?

#include <iostream> 
#include <string> 
#include <map> 

#include <boost/asio.hpp> 

typedef std::map<boost::asio::ip::address, int> Ip2Int; 
Ip2Int ip2int; 

void 
func1() 
{ 
    boost::asio::ip::address addr4 = boost::asio::ip::address::from_string("192.168.2.1"); 
    boost::asio::ip::address addr6 = boost::asio::ip::address::from_string("de::ad"); 

    ip2int.insert(std::pair<boost::asio::ip::address, int>(addr4, 1)); 
    ip2int.insert(std::pair<boost::asio::ip::address, int>(addr6, 2)); 
} 

int 
main() 
{ 
    func1(); 

    Ip2Int::iterator iter = ip2int.begin(); 
    do { 
     std::cout << iter->first << " -> " << iter->second << std::endl; 
    } while (++iter != ip2int.end()); 

    return 0; 
} 

我學習C++和上面的代碼片段中我迷惑。在func1中,addr4和addr6的分配是堆棧分配(對吧?)。當func1存在時,它們應該消失(-ish,內存將保存該值,直到其他人使用它)。這原本讓我覺得我對ip2int地圖的散步可能會打印垃圾。儘管如此,我仍然無法做到這一點。

因爲我還是新來的C++,我不排除我錯過了一些東西。一個副本是否發生在我不知道的地方?我以爲這對和地圖插入調用都只是引用。這意味着他們可以在某個時候引用垃圾。

好吧,足夠散漫。上面的代碼是否有效,或者我是幸運的,沒有其他東西可以用來存儲addr4和addr6的內存?

在此先感謝任何和所有幫助

+0

我不知道增強,但一個簡單的方法來檢查是否堆棧或堆分配是使用調試器和放置斷點(例如對構造函數)。你可能有一個堆棧分配的數據,但內部字段是堆分配的...... – 2012-02-03 17:00:13

+0

@BasileStarynkevitch你不能告訴它的堆或棧通過檢查構造函數創建相同的構造函數在兩種情況下都被調用。 – rerun 2012-02-03 17:06:58

+0

我的意思是在構造函數中,在運行時,在'gdb'調試器下面放置一個斷點....然後,如果到達構造函數,調試器將能夠顯示其'this'隱式參數,如果該指針位於堆棧或堆上,則會有線索。 – 2012-02-03 17:19:31

回答

2

是的,當你做ip2int.insert < ..>(..)。

+0

非常感謝您的快速回答。 (我不能標記這個答案,但我會在5分鐘內)你是怎麼知道的?我一直在使用http://www.cplusplus.com/reference/stl/,但我沒有發現任何提及插入內容的副本。 – user442585 2012-02-03 17:08:10

+0

@ user442585:任何時候「按值傳遞」(即沒有通過引用或指針傳遞),然後複製。 (實際上,通過指針傳遞實際上只是按值傳遞一個指針 - 也就是說,接收者自己創建指針的副本。)因此,複製是C++的基礎,而不是地圖類特有的事情。 (這就是爲什麼它沒有在STL參考中提到。) – 2012-02-03 17:24:03

+0

當您定義地圖時,insert(..)需要一對,反過來爲它的構造函數需要一個A和一個B.(即不是A&或B&)我敢肯定,如果你認爲A是一個整數,它似乎不奇怪, int被複制。一個對象在這個意義上確實沒有什麼不同。我希望更清楚一點。 – user1130005 2012-02-03 17:25:40

2

此代碼是有效的。將地址/ int對插入地圖時,實際上是製作地址對象的副本。因此,名爲「addr4」的堆棧本地地址對象不再存在,但它的一個副本(由地圖所擁有)卻不存在。這是您在函數返回時訪問的副本。

1

插入到std::map中會生成該對象的副本。原始對象addr4addr6具有自動存儲持續時間並在func1結束時被銷燬,但其副本在ip2int(其具有靜態存儲持續時間)中愉快地生活,因此保證在程序執行期間有效。

0

Stl要求使用其映射爲一個容器的對象是可複製構造的。所以聽到的是ip2int在全球範圍內是自動的,並且存在於程序的整個生命週期中。在Func1中,您正在創建兩個自動裝置並將其複製到地圖中。在地圖底層使用堆分配來包含這些值。當func1存在時,清除自動存儲器中的內存並調用析構函數,但映射仍然存在,並且創建的副本仍然存在。