[英]C++ container which automatically deletes elements when destructed
我想在C ++中创建一个引用列表或引用映射,在引用销毁后会自动删除其元素。 这是一个演示想法的结构。
class Foo;
class Bar
{
Foo foo;
};
void main(void)
{
std::vector<Foo> foos;
{
Bar bar;
foos.push_back(bar.foo);
// foos[0] should be the same reference as bar.foo
}
// bar is now destructed
// foos.size() should be 0
}
我的代码有两点错误。 当使用std :: vector调用push_back()
,它将创建Foo对象的副本。 这是不可接受的,因为foos
的元素应该反映对bar.foo
所做的任何更改。 其次,即使foos
向量可以存储引用,将Foo对象保留在创建bar
的作用域之后也不会从列表中删除。 理想情况下,我希望Foo引用在销毁后从foos
删除。
在实施自己的解决方案之前,我很想知道提供此功能的任何第三方库(可能是Boost?),或者我应该使用的任何适当的技术或策略。 谢谢!
我认为最好的选择是使用弱指针容器。 (如果您的编译器由于某种原因不支持C ++ 11或TR1,则在Boost中可用。)
假设您已正确初始化对象,则弱指针将在破坏目标时自动使自身失效。
这是一些示例代码,用于在弱指针容器中获取所有有效指针。
template <class T>
std::vector<std::shared_ptr<T> > MassLock(const std::vector<std::weak_ptr<T> >& weakptrs)
{
std::vector<std::shared_ptr<T> > sharedptrs;
for(unsigned int i=0; i<weakptrs.size(); ++i)
{
if (std::shared_ptr<T> temp = weakptrs.at(i).lock())
{
sharedptrs.push_back(temp);
}
}
return sharedptrs;
}
这是清除所有无效指针的方法。
template <class T>
struct isInvalid : public std::unary_function<T, bool>
{
bool operator() (T rhs) { return !rhs.lock(); }
};
template <class T>
void EraseInvalid( std::vector<T>& targetlist )
{
targetlist.erase( remove_if(targetlist.begin(), targetlist.end(), isInvalid<T>() ), targetlist.end());
}
如果需要多个对同一对象的引用,则可能需要一个容器,例如std::shared_ptr
(如果没有C ++ 11,则来自Boost)。
通过使用weak_ptr(由Antimony建议)来更改列表以保留引用,并按如下所示自动删除被破坏的元素。
首先,让我们澄清一些措辞:标题应该是“ C ++容器,在销毁时会自动删除对元素的引用”,因为删除元素实际上会销毁它,因此您不希望在销毁时将其“删除”,而是希望从容器中删除对它的引用。
std::list<std::weak_ptr<Foo>> foos;
{
// create a new entry in the container
const auto& iter = foos.insert(foos.end(), std::weak_ptr<Foo>());
// create an object of type "Foo" and store it in a shared_ptr
std::shared_ptr<Foo> foo
(new Foo
// set a custom deleter that actually deletes the object
// AND erases it from the container
, [&foos, iter](Foo* ptr)
{
delete ptr;
foos.erase(iter);
}
);
// set the pointer to the element into the container
*iter = foo;
}
// the shared_ptr "foo" ran out of scope;
// as there is no further strong reference to its object
// , the custom deleter was called which has removed the entry from the container
// so foos.size() is now 0
请注意,我将容器从矢量更改为列表,因为矢量可能会使迭代器无效(传递给自定义删除程序,请参见调整矢量的大小会使迭代器无效吗? ),而列表却没有。 如果要坚持使用向量,则可以使用索引作为传递给自定义删除器的元素的引用,但要注意,在end()之前在向量中插入元素会破坏该引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.