如何从 boost::ptr_vector 中删除元素

发布于 2024-07-09 10:08:32 字数 3169 浏览 7 评论 0原文

所以我试图通过使用 boost::ptr_vector 来摆脱我的 std::vector 。 现在我正在尝试从一个元素中删除一个元素,并将删除的元素也删除。 对我来说最明显的事情是:

class A
{ int m; };

boost::ptr_vector<A> vec;
A* a = new A;
vec.push_back(a);
vec.erase(a);

但这甚至无法编译(请参阅下面的完整错误消息)。 我已经尝试过像在 std::vector 上那样的擦除/删除习惯用法,但 boost::ptr_vector 的所有算法结果与 std::vector 中的算法略有不同。

所以我的问题是:

  • 如何从 ptr_vector 中删除指针?
  • 我是否仍然需要手动删除()我删除的元素?

编译器错误:

1>------ Build started: Project: ptr_vector_test, Configuration: Debug Win32 ------
1>Compiling...
1>ptr_vector_test.cpp
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2825: 'C': must be a class or namespace when followed by '::'
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\mpl\eval_if.hpp(63) : see reference to class template instantiation 'boost::range_const_iterator<C>' being compiled
1>        with
1>        [
1>            C=A *
1>        ]
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\range\iterator.hpp(63) : see reference to class template instantiation 'boost::mpl::eval_if_c<C,F1,F2>' being compiled
1>        with
1>        [
1>            C=true,
1>            F1=boost::range_const_iterator<A *>,
1>            F2=boost::range_mutable_iterator<A *const >
1>        ]
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\ptr_container\detail\reversible_ptr_container.hpp(506) : see reference to class template instantiation 'boost::range_iterator<C>' being compiled
1>        with
1>        [
1>            C=A *const 
1>        ]
1>        c:\tmp\ptr_vector_test\ptr_vector_test.cpp(21) : see reference to function template instantiation 'boost::void_ptr_iterator<VoidIter,T> boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::erase<A*>(const Range &)' being compiled
1>        with
1>        [
1>            VoidIter=std::_Vector_iterator<void *,std::allocator<void *>>,
1>            T=A,
1>            Config=boost::ptr_container_detail::sequence_config<A,std::vector<void *,std::allocator<void *>>>,
1>            CloneAllocator=boost::heap_clone_allocator,
1>            Range=A *
1>        ]
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2039: 'const_iterator' : is not a member of '`global namespace''
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2146: syntax error : missing ';' before identifier 'type'
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2208: 'boost::type' : no members defined using this type
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : fatal error C1903: unable to recover from previous error(s); stopping compilation
1>Build log was saved at "file://c:\tmp\ptr_vector_test\Debug\BuildLog.htm"
1>ptr_vector_test - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

So I'm trying to get rid of my std::vector's by using boost::ptr_vector. Now I'm trying to remove an element from one, and have the removed element deleted as well. The most obvious thing to me was to do:

class A
{ int m; };

boost::ptr_vector<A> vec;
A* a = new A;
vec.push_back(a);
vec.erase(a);

But this won't even compile (see below for the full error message). I've tried the erase/remove idiom like I would on a std::vector but all the algorithms of boost::ptr_vector turn out to be slightly different from those in std::vector.

So my questions:

  • How do I remove a pointer from a ptr_vector?
  • Do I still need to manually delete() that element that I removed?

Compiler error:

1>------ Build started: Project: ptr_vector_test, Configuration: Debug Win32 ------
1>Compiling...
1>ptr_vector_test.cpp
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2825: 'C': must be a class or namespace when followed by '::'
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\mpl\eval_if.hpp(63) : see reference to class template instantiation 'boost::range_const_iterator<C>' being compiled
1>        with
1>        [
1>            C=A *
1>        ]
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\range\iterator.hpp(63) : see reference to class template instantiation 'boost::mpl::eval_if_c<C,F1,F2>' being compiled
1>        with
1>        [
1>            C=true,
1>            F1=boost::range_const_iterator<A *>,
1>            F2=boost::range_mutable_iterator<A *const >
1>        ]
1>        c:\users\rvanhout\svn\trunk\thirdparty\boost\ptr_container\detail\reversible_ptr_container.hpp(506) : see reference to class template instantiation 'boost::range_iterator<C>' being compiled
1>        with
1>        [
1>            C=A *const 
1>        ]
1>        c:\tmp\ptr_vector_test\ptr_vector_test.cpp(21) : see reference to function template instantiation 'boost::void_ptr_iterator<VoidIter,T> boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::erase<A*>(const Range &)' being compiled
1>        with
1>        [
1>            VoidIter=std::_Vector_iterator<void *,std::allocator<void *>>,
1>            T=A,
1>            Config=boost::ptr_container_detail::sequence_config<A,std::vector<void *,std::allocator<void *>>>,
1>            CloneAllocator=boost::heap_clone_allocator,
1>            Range=A *
1>        ]
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2039: 'const_iterator' : is not a member of '`global namespace''
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2146: syntax error : missing ';' before identifier 'type'
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : error C2208: 'boost::type' : no members defined using this type
1>c:\users\rvanhout\svn\trunk\thirdparty\boost\range\const_iterator.hpp(37) : fatal error C1903: unable to recover from previous error(s); stopping compilation
1>Build log was saved at "file://c:\tmp\ptr_vector_test\Debug\BuildLog.htm"
1>ptr_vector_test - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

温柔戏命师 2024-07-16 10:08:32

那么你也可以使用 std::vector 来做到这一点。

在这两种情况下,erase 都将迭代器作为参数。
因此,在从向量(或 ptr_vector)中删除某些内容之前,您需要找到它。

另请注意,ptr_vector 将其内容视为存储了对象而不是指针。 因此任何搜索都是通过对象完成的。

所以基本上

 std::vector<A>       x;
 std::ptr_vector<A>   y;

 // These two object should behave in exactly the same way.
 // The ONLY difference is inserting values which for y are pointers.
 // Y take ownership of the pointer and all subsequent acesses to the
 // members of y look like they are objects

示例:

#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>

class A
{ int m;
    public:
    A(int x):m(x)   {}
    bool operator==(A const& rhs)   {return m = rhs.m;}
};

int main()
{
    boost::ptr_vector<A>    x;
    x.push_back(new A(1));
    x.erase(std::find(x.begin(),x.end(),A(1)));


    std::vector<A>          y;
    y.push_back(A(2));
    y.erase(std::find(y.begin(),y.end(),A(2)));

    // To find an exact pointer don't modify the equality.
    // Use find_if and pass a predicate that tests for a pointer
    A* a = new A(3);
    boost:ptr_Vector<A>     z;
    z.push_back(a);
    z.erase(std::find_if(y.begin(),y.end(),CheckPointerValue(a));
}

struct CheckPointerValue
{
     CheckPointerValue(A* a):anA(a) {}
     bool operator()(A const& x)    { return &X == anA;}
     private:
        A* anA;
};

Well you can do that with a std::vector either.

In both cases erase takes an iterator as a parameter.
So before you can erase something from a vector (or a ptr_vector) you need to locate it.

Also note that the ptr_vector treats its content as if you have stored an object not a pointer. So any searching is done via the object.

So basically

 std::vector<A>       x;
 std::ptr_vector<A>   y;

 // These two object should behave in exactly the same way.
 // The ONLY difference is inserting values which for y are pointers.
 // Y take ownership of the pointer and all subsequent acesses to the
 // members of y look like they are objects

Example:

#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>

class A
{ int m;
    public:
    A(int x):m(x)   {}
    bool operator==(A const& rhs)   {return m = rhs.m;}
};

int main()
{
    boost::ptr_vector<A>    x;
    x.push_back(new A(1));
    x.erase(std::find(x.begin(),x.end(),A(1)));


    std::vector<A>          y;
    y.push_back(A(2));
    y.erase(std::find(y.begin(),y.end(),A(2)));

    // To find an exact pointer don't modify the equality.
    // Use find_if and pass a predicate that tests for a pointer
    A* a = new A(3);
    boost:ptr_Vector<A>     z;
    z.push_back(a);
    z.erase(std::find_if(y.begin(),y.end(),CheckPointerValue(a));
}

struct CheckPointerValue
{
     CheckPointerValue(A* a):anA(a) {}
     bool operator()(A const& x)    { return &X == anA;}
     private:
        A* anA;
};
薔薇婲 2024-07-16 10:08:32

我认为你想在向量上调用 .release() 而不是擦除。 这会删除该条目并删除内存。

有关详细信息,请参阅教程中的“新函数”部分,或查看参考

或者,您需要获取元素的迭代器才能调用擦除(),我不确定 A* 是否算作 ptr_vector 。

I think you want to call .release() on the vector instead of erase. That removes the entry and deletes the memory.

See the section "New Functions" for details in the tutorial, or check the reference.

Alternatively, you need to get an iterator to an element in order to call erase(), I'm ot sure an A* counts in terms of a ptr_vector.

疯了 2024-07-16 10:08:32

您可以使用erase_if模板方法。

vec.erase_if( predicate() );

You can use erase_if template method.

vec.erase_if( predicate() );
如歌彻婉言 2024-07-16 10:08:32

ptr_vector 的语义与常规vector 非常相似。 您必须先找到一个元素,然后才能删除它。

The semantics of ptr_vector are very similar to a regular vector. You have to find an element before you can erase it.

与君绝 2024-07-16 10:08:32

奇怪的是: STL::vector 是一个 随机访问容器,这意味着它使用 随机访问迭代器

因此,vec.erase(vec.begin()+N) 将删除索引 N 处的元素。

请注意,这样做会破坏整个迭代器 meme,并且您不能再简单地在向量和列表之间切换...

Curious thing: STL::vector<> is a Random Access Container, meaning that it uses Random Access Iterators.

So vec.erase(vec.begin()+N) will remove the element at index N.

Note that doing so breaks the whole iterator meme and you can no longer trivially switch between vectors and lists...

绿萝 2024-07-16 10:08:32

您需要将成员擦除_if 方法与合适的谓词结合使用。 不需要删除指针,容器拥有所有权。

struct delete_a {
    bool operator()(boost::ptr_vector<A>::value_type inA) {
       return inA == a;
    }
}

vec.erase_if(delete_a());

(请注意,这只是为了简单起见而选择的示例,对于实际代码中的这种情况,我想人们会编写合适的 bind/equal_to 组合,或使用 lambda)

或者,作为替代方案,如果您仍然想要,可以在正确的迭代器上调用release使用该对象。

You need to use the member erase_if method with a suitable predicate. There's no need to delete the pointer, the container has ownership.

struct delete_a {
    bool operator()(boost::ptr_vector<A>::value_type inA) {
       return inA == a;
    }
}

vec.erase_if(delete_a());

(note this is just an example chosen for simplicity, for such situation in real code I suppose one would write a suitable bind/equal_to combo, or use lambda)

Or, as an alternative, call release on the correct iterator, if you still want to use the object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文