stl map <char *, char *> деструктор - PullRequest
5 голосов
/ 06 декабря 2011

Я знаю, что деструктор карты вызывает каждый из деструкторов элемента. Что происходит для

map<char*,char*> ?

Я не вижу, где находится этот код в /usr/include/c++/4.4

.

EDIT: Я должен был сказать

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

как в

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

Ответы [ 3 ]

13 голосов
/ 06 декабря 2011

Когда уничтожено 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 выходит из области видимости.

Это хорошая иллюстрация того, почему вы должны избегать использования необработанных указателей new и delete. В вашем случае, map<string,string>, вероятно, будет лучшим выбором.

EDIT:

Как уже упоминалось в комментариях @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";

}

По сути, вы вставляете элемент с ключом "foo", а затем ищете этот элемент. Протестируйте приведенный выше код, и вы обнаружите, что он не найден. Однако, если вы попробуете это:

#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";
}

... вы получаете поведение, которое действительно хотели.

6 голосов
/ 06 декабря 2011

Что происходит

Ничего.Если вы динамически распределяете память, она протечет - для char* нет автоматического деструктора.

Используйте взамен std::string или аналогичный класс.

1 голос
/ 10 января 2013

Я согласен, что 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...