2011-12-06 129 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