簡體   English   中英

如何在使用基於范圍的 for 循環遍歷 std::unique_ptr 的 std::vector 時獲得 object 的所有權?

[英]How to take ownership of an object while looping over std::vector of std::unique_ptr using a range based for loop?

我有一個std::vector<std::unique_ptr<Kind>>我想在迭代時清理它,而不顯式調用其成員的析構函數( .reset() )。

Kind是一個沉重的結構,它的大小在迭代過程中會增加。 下一個 object 不需要知道以前的對象,所以我想在不需要的時候清理一個 iterand。

我知道 vector 最終會清理干凈,但到那時,很多Kind和它們動態分配的 memory 加起來了。 我正在嘗試將峰值 memory 減少到一個元素。

我想避免reset ,因為其他開發人員可能不知道動態分配,忘記在循環結束時調用重置並花費 memory 罰款。

我無法創建副本,

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 時獲得 object 的所有權?

使用對該元素的引用進行循環,並將std::move唯一指針移動到另一個。 例子:

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

我想打掃

沒有必要保留舊的結構

您可以通過重置指針來解除分配 object:

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

也就是說,這通常是不必要的。 當 vector 走出 scope 時,它們會自動銷毀。

我想在這里保存一些 memory

如果您在迭代時分配動態對象,這可能會有用。 否則不影響高峰memory使用。

如果您想確保在每次迭代后立即刪除實例並且您不能等到整個循環完成,您可以編寫一個包裝器來處理這個問題並同時表達您的意圖:

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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM