stl map <char *, char *> destructor

Ik weet dat een destructor op de kaart alle destructors van het ingesloten element aanroept. Wat gebeurt er voor een

map ?

Ik kan niet zien waar deze code is in /usr/include/c++/4.4


BEWERK: ik had moeten zeggen

map

als in

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

5
Op GCC 4.6 moet je in /usr/include/c ++/4.6/bits/stl_map.h kijken en kijk op 4.6 in /usr/include/c ++/4.4/bits/stl_map. h
toegevoegd de auteur Basile Starynkevitch, de bron
Merk op dat een kaart geïndexeerd door char * waarschijnlijk niet zal doen wat u wilt. Het komt overeen op het tekenreeksadres, niet op de reeksinhoud.
toegevoegd de auteur Fred Larson, de bron

3 antwoord

When a map is destroyed, so are all of the elements it contains. Each element's destructor is called, if it is of class type.

Houd echter precies in gedachten wat er op uw kaart hierboven staat. Het is geen touwtjes, zoals je zou verwachten - het zijn slechts verwijzingen naar snaren. De snaren zelf worden niet vernietigd. Alleen de aanwijzers zijn. delete wordt nooit aangeroepen op de aanwijzers.

Voorbeeld:

map strings;

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

In het bovenstaande, omdat delete nooit wordt aangeroepen op de aanwijzers gemaakt door de aanroepen van new , zal dit geheugen lekken wanneer strings buiten bereik raakt .

This is a good illustration of why you should avoid using raw pointers, new and delete. In your case, map would probably be a better choice.

BEWERK:

As @sbi mentioned in the comments, another reason why you would want map over map is because with map keys are compared by-value, rather than by-pointer-value.

Overwegen:

#include 
#include 
#include 
using namespace std;

int main()
{
    static const char MyKey[] = "foo";
    const char bar[] = "bar";
    typedef map 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";

}

In principe voeg je een element in met de sleutel "foo" en dan zoek je naar dat element. Test de bovenstaande code en u zult merken dat deze niet is gevonden. Als je dit echter probeert:

#include 
#include 
#include 
using namespace std;

int main()
{
    typedef map 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";
}

... u krijgt het gedrag dat u echt wilde hebben.

14
toegevoegd
@sbi: Goed punt, bewerkt.
toegevoegd de auteur John Dibling, de bron
Uitstekend antwoord, +1 van mij. Een andere reden om de voorkeur te geven aan std :: string is dat in een std :: map , de sleutel wordt vergeleken door adres , in plaats van inhoud . Dat wil je bijna nooit.
toegevoegd de auteur sbi, de bron
+1 zeer goed antwoord
toegevoegd de auteur Bob Yoplait, de bron

Wat gebeurt er

Niets. Als u het geheugen dynamisch toewijst, lekt het - er is geen automatische destructor voor char * .

Gebruik in plaats daarvan std :: string of een soortgelijke klasse.

6
toegevoegd
Ik denk technisch dat het een destructor heeft die niets doet. (Je kunt A-> ~ char *() aanroepen. Maar het effect is hetzelfde.
toegevoegd de auteur Mooing Duck, de bron
Nou, "niets" is waarschijnlijk een beetje misleidend. Al het geheugen dat de intern toegewezen kaart voor zijn boom heeft, wordt immers verwijderd.
toegevoegd de auteur sbi, de bron

I do agree that std::map will have advantages over std::map. Specially having the key as value rather than pointer would provide the expected search/find results.

Maar soms hebben we een aanwijzer nodig in de kaartdefinitie, speciaal in het waardegedeelte wanneer het waardegedeelte van de kaart zwaar is voor een door de gebruiker gedefinieerde klasse. Met een zwaar voorwerp bedoel ik dat de constructor van de kopie van de klasse een aanzienlijke hoeveelheid werk doet. In dergelijke scenario's moet een deel van de kaart een aanwijzer zijn. Het gebruik van een onbewerkte aanwijzer zou het geheugen zoals hierboven vermeld lekken. Slimme aanwijzer zou een betere keuze zijn als er geen geheugen wordt gelekt.

Voorbeeld voorbeeld: Overweeg de onderstaande klasse

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

Overweeg de code waar de slimme aanwijzer van de bovenstaande klasse wordt gebruikt:

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

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

Uitvoer van bovenstaande code is:

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 
1
toegevoegd