簡體   English   中英

移動std :: vector <std::unique_ptr<T> &gt;到std :: vector <std::shared_ptr<T> &gt;

[英]Move std::vector<std::unique_ptr<T>> to std::vector<std::shared_ptr<T>>

有時我們有一個工廠生成std :: unique_ptr的向量,稍后我們想在類/線程/你之間共享這些指針。 因此,最好使用std :: shared_ptr。 有一種方法可以將std :: uniqe_ptr轉換為std :: shared_ptr

std::shared_ptr<int> sharedV;
std::unique_ptr<int> uniqueV(new int(2));

sharedV = std::move(uniqueV);

那么有什么簡單的方法來用std集合做這樣的事情嗎?

您可以使用std::move from <algorithm>來移動范圍。 它的行為與std::copy非常相似,但相反。 以下示例將所有unique_ptruniqueV移動到sharedV uniqueV的元素在示例的末尾都將為nullptr

#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

int main()
{

    std::vector<std::shared_ptr<int>> sharedV;
    std::vector<std::unique_ptr<int>> uniqueV;

    uniqueV.emplace_back(std::make_unique<int>(42));

    std::move(uniqueV.begin(), uniqueV.end(), std::back_inserter(sharedV));    

    return 0;
}

為了補充FrançoisAndrieux的答案std::vector有一個ranged insert()成員函數。 只是將迭代器傳遞給unique_ptr的向量將無法正常工作,但有一種方法可以將這些迭代器的解除引用從lvalues轉換為xvalues: std::move_iterator及其相應的工廠函數: std::make_move_iterator

sharedV.insert(sharedV.end(),
    std::make_move_iterator(uniqueV.begin()),
    std::make_move_iterator(uniqueV.end()));

這可能比使用std::back_inserter更有效的原因是insert()將預先知道結果大小將是什么,因此只需要完成一個分配,然后實際插入都不需要做大小檢查。

這寫起來很尷尬我會建議這個名為extend()的基於范圍的重載:

template <class T, class Range>
void extend(std::vector<T>& dst, Range&& range) {
    using std::begin; using std::end;
    if constexpr (std::is_lvalue_reference<Range>{}) {
        dst.insert(dst.end(), begin(range), end(range));
    } else {
        dst.insert(dst.end(),
            std::move_iterator(begin(range)), std::move_iterator(end(range)));
    }
}

這是C ++ 17,但在C ++ 14中很容易實現。 只需輸入更多內容。 然后你會寫:

extend(sharedV, std::move(uniqueV));

暫無
暫無

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

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