2011-12-06 102 views
5

我知道一個map析構函數會調用每個包含的元素的析構函數。對於stl map <char*,char*>析構函數

map<char*,char*> ? 

會發生什麼事,我不能看到這個代碼是在/usr/include/c++/4.4


編輯: 我應該說

map<const char*, const char*, ltstr> 

http://www.sgi.com/tech/stl/Map.html

+4

注意,一個'map'用'的char *'索引可能不會做你想做的。它將匹配字符串地址,而不是字符串內容。 –

+0

在GCC 4.6,你必須看看裏面'/ usr/include目錄/ C++/4.6 /位/ stl_map.h' 和4.6往裏'/ usr/include目錄/ C++/4.4 /位/ stl_map.h' –

回答

6

會發生什麼

沒有。如果你動態分配內存,它會泄漏 - char*沒有自動析構函數。

使用std::string或類似的類代替。

+1

好吧, 「無」可能有點誤導。畢竟,地圖內部爲其樹分配的所有內存被刪除。 – sbi

+2

我認爲_technically_它有一個析構函數不會做任何事情。 (你可以調用'A->〜char *()')但效果是一樣的。 –

14

map<char*,char*>被銷燬時,它所包含的所有元素也被銷燬。如果元素是類類型的,則調用每個元素的析構函數。

但是,請記住上圖中包含的內容。它不是字符串,正如你所期望的那樣 - 它只是指向字符串的指針。字符串本身不被破壞。只有指針是。 delete永遠不會在指針上調用。

案例:

map<char*, char*> strings; 

char* key = new char[10]; 
char* value = new char[256]; 
/* ... */ 
strings.insert(key,value); 

在上面,因爲delete不會被調用由調用new創建的指針,當strings超出這一範圍內存將泄漏。

這是您避免使用原始指針newdelete的好例子。在你的情況下,map<string,string>可能是一個更好的選擇。

編輯:

由於@sbi在評論中提到的,另一個原因,你會想map<string,string>map<char*,char*>是因爲map<string,string>鍵一起比較值,而不是通過指針值。

考慮:

#include <map> 
#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    static const char MyKey[] = "foo"; 
    const char bar[] = "bar"; 
    typedef map<const char*,const char*> Strings; 
    Strings strings; 
    strings.insert(make_pair(MyKey,bar)); 

    string ss = "foo"; 
    Strings::const_iterator it = strings.find(ss.c_str()); 
    if(it == strings.end()) 
     cout << "Not Found!"; 
    else 
     cout << "Found"; 

} 

從根本上說,你要插入一個元素與鍵「富」,然後尋找該元素。測試上面的代碼,你會發現它沒有被發現。但是,如果你試試這個:

#include <map> 
#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    typedef map<string,string> Strings; 
    Strings strings; 
    strings.insert(make_pair("foo","bar")); 

    string ss = "foo"; 
    Strings::iterator it = strings.find(ss); 
    if(it == strings.end()) 
     cout << "Not Found~!"; 
    else 
     cout << "Found"; 
} 

...你得到你真的想要的行爲。

+2

出色答卷,'+ 1'從我這裏。喜歡'的std :: string'另一個原因是,在'的std ::地圖',鑰匙就會被_address_比較,而不是_content_。你很少想要那樣。 – sbi

+0

@sbi:好點,編輯。 –

+0

+1非常好的答案 –

1

我確實認爲std::map<string, string>std::map<char*, char*>有優勢。特別是將鍵作爲值而不是指針將提供預期的搜索/查找結果。

但是,有時候我們確實需要在地圖定義指針特別是在值部分時圖的價值部分是一個用戶定義的類的重物。通過沉重的對象,我的意思是這個類的拷貝構造函數做了大量的工作。在這種情況下,地圖的值部分應該是一個指針。如上所述,使用原始指針會泄漏內存。智能指針將是一個更好的選擇,確保沒有內存泄漏。

樣品例如: 考慮以下類

class ABCD 
{ 
public: 
    ABCD(const int ab) : a(ab) 
    {cout << "Constructing ABC object with value : " << a << endl;} 

    ~ABCD() 
    {cout << "Destructing ABC object with value : "<< a << endl;} 

    void Print() 
    { cout << "Value is : " << a << endl;} 

private: 
    int a; 
}; 

考慮這樣-在上述類的智能指針被使用的代碼:

{ 
    std::map<_tstring, std::shared_ptr<ABCD>> myMap; 
    _tstring key(_T("Key1")); 
    myMap.insert(std::make_pair(key, std::make_shared<ABCD>(10))); 
    auto itr = myMap.find(key); 
    itr->second->Print(); 

    myMap[key] = std::make_shared<ABCD>(20); 
    itr = myMap.find(key); 
    itr->second->Print(); 
} // myMap object is destroyed, which also calls the destructor of ABCD class 

輸出從上面的代碼是:

Constructing ABC object with value : 10 

Value is : 10 

Constructing ABC object with value : 20 

Destructing ABC object with value : 10 

Value is : 20 

Destructing ABC object with value : 20