使用基于范围的for循环在std::unique_ptr的std::vector上循环时,如何获得对象的所有权



我有一个std::vector<std::unique_ptr<Kind>>,我想在迭代它时清理它,而不显式调用其成员的析构函数(.reset()(。

Kind是一个沉重的结构,它的大小在迭代过程中会增加。下一个对象不需要知道以前的对象,所以我想在不需要iterand的时候清理它。

我知道vector最终会清理干净,但到那时,许多Kind和它们动态分配的内存加起来了。我正试图将峰值记忆减少到一个元素。

我想避免reset,因为其他开发人员可能不知道动态分配,忘记了在循环结束时调用reset和消耗内存。

我无法创建副本,

for(std::unique_ptr<Kind> t : store)

我不能像那样移动它

for(std::unique_ptr<Kind> &&t : store)

那我该怎么做呢?

#include <iostream>
#include <vector>
struct Kind{
char a;
char *array;
Kind(const char c): a(c)
{
}
~Kind(){
free(array); // internal custom deallocator.
}
};
int main() {
std::vector<std::unique_ptr<Kind>> store;
store.push_back(std::make_unique<Kind>('y'));
store.push_back(std::make_unique<Kind>('z'));
for(std::unique_ptr<Kind> &t : store){
// increase size of Kind.array.
std::cout << t->a;
// Use the Kind.array
// clean up t automatically.
}
return 0;
}

将元素移出向量的示例。

int main() {
std::vector<std::unique_ptr<Kind>> store;
store.push_back(std::make_unique<Kind>('y'));
for(std::unique_ptr<Kind> &t : store){
auto tmp = std::move(t); // leaving a valid but empty entry in store
std::cout << tmp->a;
// clean up t automatically.
// tmp runs out of scope and cleans up
}
return 0;
}

实际上,与重置没有太大区别,但可能与您在实际程序中实际做的事情有关。

如何在使用基于范围的for循环遍历std::unique_ptr的std::vector时获得对象的所有权?

循环引用元素,std::move将唯一指针指向另一个元素。示例:

for(std::unique_ptr<Kind> &t : store){
std::unique_ptr<Kind> owner = std::move(t);
// do something with newly owned pointer

我想清理

没有必要在周围保留较旧的结构

您可以通过重置指针来解除分配对象:

for(std::unique_ptr<Kind> &t : store) {
// do something
t.reset();

也就是说,这通常是不必要的。当矢量超出范围时,它们将被自动销毁。

我正试图在这里保存一些内存

如果在迭代时分配动态对象,这可能会很有用。否则,它不会影响峰值内存使用。

如果你想确保在每次迭代后立即删除实例,并且不能等到整个循环完成,你可以编写一个包装器来处理这个问题,同时表达你的意图:

template <typename T>
struct Stealing {
std::unique_ptr<T> ptr;
Stealing(std::unique_ptr<T>& ptr) : ptr(std::move(ptr)) {
}   
auto operator*() {
return ptr.operator*();
}   
auto operator->() {
return ptr.operator->();
}   
}

您可以在循环中使用它来替换unique_ptr,如下所示:

for (Stealing<Kind> t: store) {
// do what you like with t as if it was a std::unique_ptr
// when t goes out of scope, so does its member -> Kind gets destroyed
}

最新更新