如何清除std :: map <k,v *>容器并安全删除所有指向的对象?

时间:2018-03-26 15:34:49

标签: stdmap c++98

所有标准库容器都不会在包含的原始指针上调用delete。我已在SO C++98检查了解决方案,但未找到答案。

我已创建template <typename K, typename V> void clearAndDestroy( std::map<K, V*> *&myMap)作为std::clear()的替换函数(删除所有元素并调用析构函数)。

适用于带有指向对象std::map(key,V*)的指针的地图。该函数也适用于map包含不同键的相同V *指针的情况。

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

using namespace std;

// clearAndDestroy deletes all objects and remove them from the std::map(K,V*) container.
template <typename K, typename V>
void clearAndDestroy( std::map<K, V*> *&myMap)
{
    if(myMap == NULL)
        return;

    std::set<V*> mySet;

    typename std::map<K,V*>::iterator itr;
    typename std::set<V*>::iterator sitr;

    itr = myMap->begin();
    while (itr != myMap->end()) {
        mySet.insert(itr->second);
        ++itr;
    }

    sitr = mySet.begin();
    while (sitr != mySet.end()) {
        delete(*sitr);
        ++sitr;
    }

    myMap->clear();
}

template <typename K, typename V> void clear1( std::map<K, V*> *myMap)
{
    if(myMap == NULL) return;
    typename std::map<K, V*>::iterator itr = myMap->begin();

    while (itr != myMap->end()) {
        typename std::map<K, V*>::iterator toErase = itr;
        ++itr;
        myMap->erase(toErase);
        delete(toErase->second);
    }
}

template <typename M> void clear2( M *myMap )
{
    if(myMap == NULL) return;

    for ( typename M::iterator it = myMap->begin(); it != myMap->end(); ++it ) {
        delete it->second;
    }
    myMap->clear();
}

class MY_CLASS
{
public:
    int counter;
    string *message;

    MY_CLASS(int c, string *m):counter(c), message(m) {
        std::cout << "Constructor MY_CLASS " << this << std::endl;
    };
    ~MY_CLASS()
    {
        if(message) {
            cout << "Being destroyed MY_CLASS: " << *message << " this = " << this <<endl;
        }
        else {
            cout << "Being destoyed MY_CLASS: " << " this = " << this <<endl;
        }

        if(message) {
            delete message;
            message = NULL;
        }
    }

    MY_CLASS(const MY_CLASS & other)
    {
        std::cout << "Copy Constructor MY_CLASS " << this << std::endl;
        //1.
        counter = other.counter;
        //2.
        if(other.message) {
            message  = new string;
            *message = *other.message; // copy the value
        }
        else {
            message = NULL;
        }
    }
};

void print(const string *str,MY_CLASS *& value, void *)
{
    if (value && value->message)
        cout << value->counter << " ! " << *(value->message) << endl;
}

int main() {

    std::map<std::string, MY_CLASS *> *mpa = new std::map<std::string, MY_CLASS *>;
    MY_CLASS *p = new MY_CLASS(2, new string("abc"));

    mpa->insert(std::pair<std::string, MY_CLASS *>("1", p));
    mpa->insert(std::pair<std::string, MY_CLASS *>("2", p));

    clearAndDestroy(mpa);
    delete mpa;

    return 0;
}

输出:

Constructor MY_CLASS 0x111ccb0                                                                                                                 
Being destroyed MY_CLASS: abc this = 0x111ccb0 

限制使用C ++ 98 clearAndDestroy是我最好的选择吗?谢谢!

1 个答案:

答案 0 :(得分:0)

您可以采用的另一种方法是使用对象包装器。将所需指针放在一个对象中,让析构函数调用指针上的delete。基本上构建一个简单的“智能指针”。

class AutoDeletePtr {
    MY_CLASS* pointer;
    AutoDeletePtr(MY_CLASS* myObjectPtr) {pointer = myObjectPtr};
    ~AutoDeletePtr() {delete(pointer)};
}

您可以将这些对象插入到std :: map。