【问题标题】:std::set deleter in C++ is not workingC++ 中的 std::set 删除器不起作用
【发布时间】:2016-04-17 20:56:40
【问题描述】:

我在这里定义了自己的删除器,但不确定为什么不起作用。 其次,有什么方法可以不使用 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)'

【问题讨论】:

  • 定义“不起作用”。充分解释您期望发生的事情以及实际发生的事情。
  • 编译器在我使用 for_each 循环的地方显示错误。
  • Second is there any way of not using for_each loop and just defining deleter using it at the time of set declaration makes all objects get deleted automatically when the set object goes out of scope . 是 - std::unique_ptr.
  • 编译器的完整报告看起来很奇怪,请编辑您的问题以提高可读性。

标签: c++ memory-leaks stl set


【解决方案1】:

提供的代码由于几个原因无法编译:

  1. Deleter 中缺少模板参数
  2. 您的比较器在需要比较 A* 时比较 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;
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2020-08-06
  • 2012-09-22
  • 2010-11-06
  • 1970-01-01
  • 2014-04-15
  • 2011-02-21
相关资源
最近更新 更多