【发布时间】:2011-09-15 05:44:28
【问题描述】:
我有一个指向对象的指针向量。我需要从向量中删除一个元素并将该元素放在另一个列表中。
我读到擦除可用于从向量中删除对象,但我也读到它在这样做之前调用对象析构函数。
我需要知道擦除对象是否也会破坏它。
【问题讨论】:
我有一个指向对象的指针向量。我需要从向量中删除一个元素并将该元素放在另一个列表中。
我读到擦除可用于从向量中删除对象,但我也读到它在这样做之前调用对象析构函数。
我需要知道擦除对象是否也会破坏它。
【问题讨论】:
vector::erase
从向量容器中删除并调用其析构函数,但如果包含的对象是指针,则它不会拥有销毁它的所有权。
您必须在每个包含的指针上显式调用 delete 以删除它指向的内容,例如:
void clearVectorContents( std::vector <YourClass*> & a )
{
for ( int i = 0; i < a.size(); i++ )
{
delete a[i];
}
a.clear();
}
在标准容器中存储原始指针不是一个好主意。如果您确实需要存储必须由new 分配的资源,那么您应该使用boost::shared_ptr。查看Boost documentation。
更通用和优雅的解决方案:
正如@Billy 在 cmets 中指出的那样,该解决方案利用了 for_each 和 templates:
// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
public:
// Overloaded () operator.
// This will be called by for_each() function.
bool operator()(T x) const
{
// Delete pointer.
delete x;
return true;
}
};
这可以称为:
for_each( myclassVector.begin(),myclassVector.end(),
DeleteVector<myclass*>());
其中,myclassVector 是您的向量,其中包含指向 myclass 类对象的指针。
用法示例:
#include "functional"
#include "vector"
#include "algorithm"
#include "iostream"
//Your class
class myclass
{
public:
int i;
myclass():i(10){}
};
// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
public:
// Overloaded () operator.
// This will be called by for_each() function.
bool operator()(T x) const
{
// Delete pointer.
delete x;
return true;
}
};
int main()
{
// Add 10 objects to the vector.
std::vector<myclass*> myclassVector;
for( int Index = 0; Index < 10; ++Index )
{
myclassVector.push_back( new myclass);
}
for (int i=0; i<myclassVector.size(); i++)
{
std::cout << " " << (myclassVector[i])->i;
}
// Now delete the vector contents in a single line.
for_each( myclassVector.begin(),
myclassVector.end(),
DeleteVector<myclass*>());
//Clear the vector
myclassVector.clear();
std::cout<<"\n"<<myclassVector.size();
return 0;
}
【讨论】:
"but If the contained object is a pointer it doesnt take ownership of destroying it."
vector<MyObject>,那么MyObject::~MyObject 将是
调用。vector<MyObject*>,则不会调用delete <MyObject
instance>。要在两个向量之间移动 MyObject,您需要先将其插入到目标向量中,然后擦除原始向量。请注意,这将创建对象的新副本。移动指针时,您可以将指针保存在临时变量中,将其从向量中擦除,然后插入到您需要的任何位置。
这是另一种简单的方法来删除然后删除向量中的所有项目:
template<class T> void purge( std::vector<T> & v ) {
for ( auto item : v ) delete item;
v.clear();
}
【讨论】:
是的,erase 会破坏元素。但是,如果您将元素放在另一个容器中,您可能会制作一个副本,将其放入另一个容器中。遇到问题的唯一方法是将指针或类似的东西复制到另一个容器中。
【讨论】:
delete )
vector<Plane *> p, q;Plane *r = new Plane();p.push_back(r);q.push_back(r);p.erase(p.begin());r 和 q.begin() 仍然会引用新创建的平面?
{ Plane * p = new Plane; } 的行为相同,当p 超出范围时,它被“销毁”但分配的对象仍然存在于堆上。使用裸指针使它们你的责任。
是的。 vector::erase 销毁被移除的对象,这涉及到调用它的析构函数。
【讨论】:
是的,当然会。如果向量中不存在该对象,它还会存在于哪里?
编辑:这将不会删除指针指向的任何内容。您应该使用自动生命周期管理指针,例如 shared_ptr 来管理对象生命周期。
【讨论】: