使用模板删除任何容器

时间:2010-12-18 18:20:52

标签: c++ visual-studio-2008 templates

我有很多代码,我要删除其中有指针的向量容器,也就是说,我必须首先删除所有指针,然后清除容器。每次我迭代并手动删除指针(我知道stl :: algorithms for_each)。为了绕过所有代码,我创建了一个模板来删除所有带指针的向量容器。到目前为止一切都很好。

现在我还有几个容器类型,包括地图,并发容器等。就删除而言,最终都具有相同的功能。我拥有的DeleteContainer(std::vector<T*>& VecIn)函数只能用于上面提到的向量。有没有办法让它足够通用,可以处理所有容器?

  

编辑:感谢所有答案,我希望我能选择多个答案。对于任何偶然发现这个问题的人,请阅读所有答案,而不仅仅是所选答案,因为它们都提供了很好的信息。

7 个答案:

答案 0 :(得分:7)

您已经有了一个有效的答案,但只是为了提供替代方案,我相信您应该考虑使用Boost Pointer Container并让它处理内存管理:

  

这个库因此提供   类似于标准的容器   存储堆分配或克隆   对象(或在地图的情况下,   映射对象必须是堆分配的   或克隆的对象)。 对于每个人   标准容器有一个指针   容器等价物   一个对象的所有权   例外安全方式。

答案 1 :(得分:4)

您可以使用增强指针容器 它们正确地保存和删除指针。

http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/doc/reference.html

{
    boost::ptr_vector<int>   data;

    data.push_back(new int(2));
    data.push_back(new int(2));
    data.push_back(new int(2));
}
// container deleted and all pointers correctly destroyed.

答案 2 :(得分:4)

我会使用shared_ptr或者提升指针容器来吸引更多人。但是,你可以写

template <typename Iter>  
void delete_pointers(Iter begin, Iter end)
{
    for (; begin != end; ++begin) delete *begin;
}

用法:

std::vector<Foo*> v;

// Initialize Foo objects

delete_pointers(v.rbegin(), v.rend());

我使用rbeginrend代替beginend,因为有时人们希望以与创建对象相反的顺序删除对象。

您也可以

void destroyFoo(Foo* x) { delete x; }

std::for_each(v.rbegin(), v.rend(), &destroyFoo);

或使用C ++ 0x lambdas。

答案 3 :(得分:3)

您可以使用boost::shared_ptr<T> T* DeleteContainertemplate<class T> void DeleteContainer(typename T::iterator begin, typename T::iterator end) { for(;begin!=end;++begin) delete *begin; } 没有理由。std::some_container<int*> s; DeleteContainer<std::some_container<int*> > (s.begin(), s.end()); 。但如果你不想这样做,你可以做这样的事情

{{1}}

然后您可以通过这种方式为任何所需的stl容器调用它:

{{1}}

答案 4 :(得分:1)

正如Tomek所建议的,我们可以有类似的解决方案来处理删除。结构本身比自由函数更好。

struct Delete
{
   public:
      template<typename T>
      void operator()(const T* ptr) const
      {
          delete ptr;
      }
      void operator()(const char* ptr) const
      {
          delete[] ptr;

     }
};

for_each(some_container.begin(),some_container.end(),Delete());

答案 5 :(得分:0)

另一种方法是放弃完全删除内容并承诺使用垃圾收集器:)您可以尝试使用Boehm-Reiser-Detlefs收集器,它是Linux(libgc)的标准配置,现在用于许多复杂程序(比如gcc)。放弃RAII也是一个好主意:当时这是一个不错的主意但它在实践中并没有那么好用。许多资源都是独立创建的,并且无法通过其代表进行销毁。

答案 6 :(得分:0)

我对此的看法是:

template<class T>
void Destroy(T *p)
{
  delete p;
}

template<template<typename, typename> class C, typename T1, typename T2>
void Destroy(C<T1 *, T2> &c)
{                                                        
  std::for_each(c.begin(), c.end(), Destroy<T1>);
}

使用vector,deque和list在g ++ 4.4.4上测试。对于其他容器和/或其他STL实现,您可能需要额外的void Destroy(C&lt; T1 *,T2&gt;&amp; c)重载。