我将如何使用的for_each在STL地图删除所有的价值呢?

问题描述 投票:7回答:4

假设我有一个STL地图,该值是指针,我想将它们全部删除。我如何将代表下面的代码,但利用的std :: for_each的吗?我很高兴的解决方案,使用升压。

for( stdext::hash_map<int, Foo *>::iterator ir = myMap.begin();
     ir != myMap.end();
     ++ir )
{
  delete ir->second; // delete all the (Foo *) values.
}

(我发现Boost的checked_delete,但我不知道如何应用到迭代器代表pair<int, Foo *>)。

(另外,对于这个问题的目的,忽视的事实是存储需要在STL容器删除原始指针不是非常明智的)。

注:我后来发现下面列出的一个单行的答案...但代码是很可怕,所以我已经接受GMAN的理智的答案。

c++ algorithm boost stl
4个回答
14
投票

你必须做一个函数对象:

struct second_deleter
{
    template <typename T>
    void operator()(const T& pX) const
    {
        delete pX.second;
    }
};

std::for_each(myMap.begin(), myMap.end(), second_deleter());

如果您使用的提升,你也可以使用λ文库:

namespace bl = boost::lambda;
std::for_each(myMap.begin(), myMap.end(), second_deleter(),
                bl::bind(bl::delete_ptr(), 
                bl::bind(std::select2nd<myMap::value_type>(), _1));

但是你可以尝试pointer containers库,自动执行此操作。

请注意,您使用的不是地图,而是一个hash_map。我建议您切换到升压转换器的unordered_map,这是更大的电流。然而,似乎没有成为一个ptr_unordered_map

为了安全,你应该穿得这件事情了。例如:

template <typename T, typename Deleter>
struct wrapped_container
{
    typedef T container_type;
    typedef Deleter deleter_type;

    wrapped_container(const T& pContainer) :
    container(pContainer)
    {}

    ~wrapped_container(void)
    {
        std::for_each(container.begin(), container.end(), deleter_type());
    }

    T container;
};

并使用它,如:

typedef wrapped_container<
            boost::unordered_map<int, Foo*>, second_deleter> my_container;

my_container.container./* ... */

这确保不管是什么,你的容器将通过与有删除重复。 (有关例外,例如)。

相比:

std::vector<int*> v;
v.push_back(new int);

throw "leaks!"; // nothing in vector is deleted

wrapped_container<std::vector<int*> > v;
v.container.push_back(new int);

throw "no leaks!"; // wrapped_container destructs, deletes elements

3
投票

你是否尝试过使用BOOST_FOREACH?这应该允许你这样做,在一个行而不创建自己的仿函数。

我没有测试过下面的代码,但它应该是这个样子(即使不完全):

typedef stdext::hash_map<int, Foo *> MyMapType; //see comment.
BOOST_FOREACH( MyMapType::value_type& p, myMap )
{
    delete p.second;
}

那么这就是超过1线,由于typedef的:)


0
投票

好吧,我发现了如何做到这一点的一条线......但我不认为我会永远实际上做下面的实际代码!

std::for_each( mayMap.begin()
             , myMap.end()
             , boost::bind( &boost::checked_delete<Foo>
                          , boost::bind( &stdext::hash_map<int, Foo *>::value_type::second, _1 ) ) );

不过我会接受GMAN的答案,因为我喜欢他的一包装的容器的想法,我的答案,尽管是作为请求一行,只是普通的讨厌。


0
投票

如果可能的话,你应该在你的地图使用智能指针。

使用智能指针的位置,就不再需要重构和调试成员删除。少了一个内存管理操心前进。任何时候,我用新/删除我觉得真的很难了解这是否是必要的。个人的“代码味道”(每Martin Fowler的),如果你喜欢。

当然,如果你的旧代码返回一个地图,那么for_each的方法可能是你最好的选择 - 但如果你有一些携手创建地图,我推荐使用智能指针。

© www.soinside.com 2019 - 2024. All rights reserved.