C ++中的std :: set deleter不起作用

时间:2016-04-17 20:56:41

标签: c++ memory-leaks stl set

这里我已经定义了自己的删除器,但不确定为什么不能正常工作。 其次是没有使用for_each循环的任何方法,只是在set声明时使用它定义删除器会使所有对象在set对象超出范围时自动被删除。

#include <iostream>
#include <memory>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
class A
{
    int i;
    public:
    A(int pi):i(pi) {}
    int intake() const { return i; }
    void show() { cout<<i<<endl; }
    ~A() { cout<<"Destructor : "<<i<<endl; }
};
template <typename T>
struct Deleter
{
  void operator () (T *ptr)
  {
     delete ptr;
  }
};
struct A_comp 
{
    bool operator() (const A & lhs, const A & rhs) const
    {
              return lhs.intake() < rhs.intake();
    }
};
int main()
{
   set <A *,A_comp> s;
   s.emplace(new A(40));
   s.emplace(new A(10));
   s.emplace(new A(30));
   s.emplace(new A(20));
   set <A *,A_comp>::iterator it;
   for(it = s.begin(); it != s.end() ; it++)
      (*it)->show();
   for_each (s.begin (), s.end (), Deleter());     // Line 41
   return 0;
}

编译器错误:

In function 'int main()': 41:43: error: missing template arguments before '(' token In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h: In instantiation of 'std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = A*; _Val = A*; _KeyOfValue = std::_Identity<A*>; _Compare = A_comp; _Alloc = std::allocator<A*>; std::_Rb_tree<_Key, _Val,
_KeyOfValue, _Compare, _Alloc>::key_type = A*]': /usr/include/c++/4.9/bits/stl_tree.h:1748:55:   required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key,
_Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_unique(_Args&& ...) [with _Args = {A*}; _Key = A*; _Val = A*; _KeyOfValue = std::_Identity<A*>; _Compare = A_comp; _Alloc = std::allocator<A*>]' /usr/include/c++/4.9/bits/stl_set.h:453:64:   required from 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>,
_Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::emplace(_Args&& ...) [with
_Args = {A*}; _Key = A*; _Compare = A_comp; _Alloc = std::allocator<A*>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename
__gnu_cxx::__alloc_traits<_Allocator>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<A*>]' 34:23:   required from here /usr/include/c++/4.9/bits/stl_tree.h:1445:11: error: invalid user-defined conversion from 'const key_type {aka A* const}' to 'const A&' [-fpermissive]
    __comp = _M_impl._M_key_compare(__k, _S_key(__x));
           ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'const key_type {aka A* const}' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1445:11: error: invalid conversion from 'std::_Rb_tree<A*, A*, std::_Identity<A*>, A_comp, std::allocator<A*> >::key_type {aka A*}' to 'int' [-fpermissive]
    __comp = _M_impl._M_key_compare(__k, _S_key(__x));
           ^ 11:5: note: initializing argument 1 of 'A::A(int)' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1445:11: error: invalid user-defined conversion from 'A* const' to 'const A&' [-fpermissive]
    __comp = _M_impl._M_key_compare(__k, _S_key(__x));
           ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'A* const' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1445:11: error: invalid conversion from 'A*' to 'int' [-fpermissive]
    __comp = _M_impl._M_key_compare(__k, _S_key(__x));
           ^ 11:5: note: initializing argument 1 of 'A::A(int)' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1456:7: error: invalid user-defined conversion from 'A* const' to 'const A&' [-fpermissive]
       if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
       ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'A* const' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1456:7: error: invalid conversion from 'A*' to 'int' [-fpermissive]
       if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
       ^ 11:5: note: initializing argument 1 of 'A::A(int)' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1456:7: error: invalid user-defined conversion from 'const key_type {aka A* const}' to 'const A&' [-fpermissive]
       if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
       ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'const key_type {aka A* const}' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1456:7: error: invalid conversion from 'std::_Rb_tree<A*, A*, std::_Identity<A*>, A_comp, std::allocator<A*> >::key_type {aka A*}' to 'int' [-fpermissive]
       if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
       ^ 11:5: note: initializing argument 1 of 'A::A(int)' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h: In instantiation of 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = A*; _Val = A*; _KeyOfValue = std::_Identity<A*>; _Compare = A_comp; _Alloc = std::allocator<A*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<A*>; std::_Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<A*>*]': /usr/include/c++/4.9/bits/stl_tree.h:1750:65:   required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key,
_Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_unique(_Args&& ...) [with _Args = {A*}; _Key = A*; _Val = A*; _KeyOfValue = std::_Identity<A*>; _Compare = A_comp; _Alloc = std::allocator<A*>]' /usr/include/c++/4.9/bits/stl_set.h:453:64:   required from 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>,
_Compare, typename __gnu_cxx::__alloc_traits<_Allocator>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::emplace(_Args&& ...) [with
_Args = {A*}; _Key = A*; _Compare = A_comp; _Alloc = std::allocator<A*>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename
__gnu_cxx::__alloc_traits<_Allocator>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<A*>]' 34:23:   required from here /usr/include/c++/4.9/bits/stl_tree.h:1693:8: error: invalid user-defined conversion from 'A* const' to 'const A&' [-fpermissive]
        || _M_impl._M_key_compare(_S_key(__z),
        ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'A* const' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1693:8: error: invalid conversion from 'A*' to 'int' [-fpermissive]
        || _M_impl._M_key_compare(_S_key(__z),
        ^ 11:5: note: initializing argument 1 of 'A::A(int)' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1693:8: error: invalid user-defined conversion from 'A* const' to 'const A&' [-fpermissive]
        || _M_impl._M_key_compare(_S_key(__z),
        ^ 11:5: note: candidate is: A::A(int) <near match> 11:5: note:   no known conversion for argument 1 from 'A* const' to 'int' In file included from /usr/include/c++/4.9/set:60:0,
                 from 4: /usr/include/c++/4.9/bits/stl_tree.h:1693:8: error: invalid conversion from 'A*' to 'int' [-fpermissive]
        || _M_impl._M_key_compare(_S_key(__z),
        ^ 11:5: note: initializing argument 1 of 'A::A(int)'

1 个答案:

答案 0 :(得分:2)

提供的代码没有编译,原因如下:

  1. 在Deleter中缺少模板参数
  2. 您的比较者在需要比较A *
  3. 时比较A.

    如果你不使用指针,那么当集合超出范围时,你的对象将被删除。

    另外你可以使用std:unique_ptr,代码如下:

    #include <iostream>
    #include <memory>
    #include <string>
    #include <set>
    #include <algorithm>
    using namespace std;
    class A
    {
        int i;
        public:
        A(int pi):i(pi) {}
        int intake() const { return i; }
        void show() { cout<<i<<endl; }
        ~A() { cout<<"Destructor : "<<i<<endl; }
    };
    template <typename T>
    struct Deleter
    {
      void operator () (T *ptr)
      {
         delete ptr;
      }
    };
    struct A_comp 
    {
        bool operator() (const std::unique_ptr<A>& lhs, const std::unique_ptr<A>& rhs) const
        {
                  return lhs->intake() < rhs->intake();
        }
    };
    int main()
    {
       set <std::unique_ptr<A> ,A_comp> s;
       s.emplace(std::unique_ptr<A>(new A(40)));
       s.emplace(std::unique_ptr<A>(new A(10)));
       s.emplace(std::unique_ptr<A>(new A(30)));
       s.emplace(std::unique_ptr<A>(new A(20)));
       for(auto it = s.begin(); it != s.end() ; it++)
          (*it)->show();
       return 0;
    }