簡體   English   中英

C ++ 11中unique_ptr的向量

[英]vector of unique_ptr in C++11

我最近切換到C ++ 11,我試圖習慣那里的良好實踐。 我最終經常處理的是:

class Owner
{
private:
    vector<unique_ptr<HeavyResource>> _vectorOfHeavyResources;
public:
    virtual const vector<const HeavyResource*>* GetVectorOfResources() const;
};

這需要我做一些事情,比如添加一個_returnableVector並翻譯源向量以便以后能夠返回它:

_returnableVector = vector<HeavyResource*>;
for (int i=0; i< _vectorOfHeavyResources.size(); i++)
{
    _returnableVector.push_back(_vectorOfHeavyResources[i].get());
}

有人注意到類似的問題嗎? 您有什么想法和解決方案? 我是否在這里獲得了所有的所有權想法?

更新:還有另一件事:如果一個類返回一些處理結果作為vector<unique_ptr<HeavyResource>> (它將結果的所有權傳遞給調用者),它應該用於某些后續處理:

vector<unique_ptr<HeavyResource>> partialResult = _processor1.Process();
// translation
auto result = _processor2.Process(translatedPartialResult); // the argument of process is vector<const HeavyResource*>

我建議您不要維護和返回un- unique_ptr ed向量,而是提供直接訪問元素的函數。 這封裝了資源的存儲空間; 客戶端不知道它們存儲為unique_ptr ,也不知道它們保存在vector

一種可能性是使用boost::indirect_iterator自動取消引用您的unique_ptr

using ResourceIterator =
     boost::indirect_iterator<std::vector<std::unique_ptr<HeavyResource>>::iterator,
                              const HeavyResource>;
ResourceIterator begin() { return std::begin(_vectorOfHeavyResources); }
ResourceIterator end() { return std::end(_vectorOfHeavyResources); }

演示

如果經常遇到這種情況,編寫一個類似unique_ptr的類可能是有意義的,但是將指針的常量傳遞給它指向的對象。 這樣,您可以只返回向量的const引用。

我最后寫了一次並完成了它:

#include <iostream>
#include <vector>
#include <memory>

//unique,const-preserving pointer
template<class T>
class ucp_ptr {
    std::unique_ptr<T> ptr;
public:
    ucp_ptr() = default;
    ucp_ptr(T* ptr) :ptr{ ptr }{};
    ucp_ptr(std::unique_ptr<T>&& other) :ptr(std::move(other)){};

    T&        operator*()       { return ptr.get(); }
    T const & operator*()const  { return ptr.get(); }

    T*        operator->()      { return ptr.get(); }
    T const * operator->()const { return ptr.get(); }
};

struct Foo {
    int a = 0;
};

int main() {
    std::vector<ucp_ptr<Foo>> v;
    v.emplace_back(new Foo());
    v.emplace_back(std::make_unique<Foo>());    

    v[0]->a = 1;
    v[1]->a = 2;

    const std::vector<ucp_ptr<Foo>>& cv = v;

    std::cout << cv[0]->a << std::endl; //<-read access OK
    //cv[1]->a = 10; //<-compiler error
}

當然,如果您需要自定義刪除程序或想要添加管理數組的專門化,您可以稍微擴展它,但這是基本版本。 我也相信我已經在SO上看到了這個som的更精致的版本,但我現在找不到它。

這是一個如何在類中使用它的示例:

class Bar {
    std::vector<ucp_ptr<Foo>> v;
public:
    void add(const Foo& foo){ 
        v.push_back(std::make_unique<Foo>(foo)); 
    }
    //modifying elements
    void doubleElements() {
        for (auto& e : v){
            e->a *= 2;
        }
    }
    const std::vector<ucp_ptr<Foo>>& showElements() const{
        return v;
    }
};

編輯

就你的更新而言,你必須忍受vector<T>vector<B>無關的事實,即使將T轉換為B是有效的,反之亦然。
你可以編寫適配器,給你一個不同的元素視圖(通過在必要時強制轉換每個元素)但是 - 除了創建一個正確類型的新向量 - 沒有一般的meachanism(我知道)做什么你要。

您可能需要考慮使用shared_ptr ,因為它可能反映了您要實現的目標。 您可能希望在較小的范圍中使用unique_ptr ,或者只希望使用對象反映一件事。

我試過這個:

public:
   const std::vector<int const *> getResource()
   {
       return reinterpret_cast<std::vector<const int *> &>(resources);
   }

private:
   std::vector<unique_ptr<int>> resources;

有效。

暫無
暫無

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

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