[英]Create std::vector in-place from raw data
給定一個原始數組元素,如何創建一個std::vector
,它獲取原始數組的所有權而無需重新分配和復制?
例如,具有原始數組:
int* elems = new int[33]
如何創建一個大小為33
的std::vector
指向elems
?
我確信理論上這是可能的,因為通常std::vector
被實現為包含三個指針的結構,一個指向已分配內存的開頭,一個指向有效元素的末尾,一個指向結尾分配內存。 但是有沒有一種標准方法用原始數組初始化std::vector
結構?
你需要的是一個“視圖”而不是一個容器。 容器擁有它們的元素,它們的主要目的是封裝它們管理的原始內存。 如果您需要自己管理內存,那么您不需要容器。 如果您有一個string
,請查看string_view
,這將是您的解決方案。 也許你可以應用提升范圍 。 從文檔(強調我的):
Range概念的動機是有許多有用的類似容器的類型不能滿足Container的全部要求,並且許多算法都可以用這個減少的要求集來編寫。 特別是,Range不一定
- 擁有可以通過它訪問的元素 ,
- 有復制語義,
PS:實際上std::array_view
被認為是C ++ 17,但遺憾的是它並沒有成為標准。
這不能直接實現的原因是標准庫使用分配器為容器保留內存。
因此,如果你有一個使用某種類型的分配器的std::vector
並給它一些你創建的指針,你就會有效地打破分配器的習慣用法。 例如,如果您的標准庫的實現使用malloc
和free
而不是new
和delete
,那么您的程序將失敗。
為了使其成為標准方式 ,標准庫需要提供一個接受T*
的構造函數,該T*
還必須由向量稍后使用的相同分配器返回。 所以你需要的構造函數的簽名就像std::vector::vector(T* data, size_type used_elements, size_type capacity, const Allocator& alloc)
。 請注意,allocator參數是必需的,因為T*
必須(理論上)由向量中使用的完全相同的分配器返回。
您可以通過根據此概念創建自己的分配器來實現
某些功能
,但是為了不重構您的33
元素,您還必須提供allocator::construct(..)
函數,這是一個無操作直到第34th
元素(獨家)。 此外,您必須首先將矢量調整為33
元素,以強制矢量具有正確的大小。
盡管如此,這是一個壞主意,因為對於條件構造和分配函數,您可能會有更多的開銷,而不是復制元素一次。
根據這一點 ,沒有構造函數接受指向數據的指針。 因此,您無法將原始數組的所有權傳遞給向量。
您只能創建一個向量並將數據放入其中。
給定一個原始數組元素,如何創建一個
std::vector
,它獲取原始數組的所有權而無需重新分配和復制?
沒有辦法。
如何創建一個大小為33的
std::vector
指向elems?
不可能。
我確信理論上這是可能的,
不,不是。
但是有沒有一種標准方法用原始數組初始化
std::vector
結構?
沒有。
話雖如此,您可能能夠使用自定義分配器將解決方案混合在一起。 但是,除了編寫自定義分配器是一種很少使用的容易出錯的技術之外,您不應該高估這種解決方案的可用性。
std::vector<int>
和std::vector<int, MyAllocator>
是兩個不同的類 。 如果你的目標是與期望std::vector<int>
代碼接口,那么就不能使用std::vector<int, MyAllocator>
; 如果你打算在你的代碼中創建和使用std::vector<int, MyAllocator>
,那么老實說你最好只是實現你自己的非擁有容器類,比如自定義VectorView<T>
。
如果您正在處理的對象的類型是可移動的,則可以執行以下操作:
template<typename T>
std::vector<std::unique_ptr<T>> ConvertArrayToVector(T* data, size_t size)
{
std::vector<std::unique_ptr<T>> result(size);
for (unsigned int i = 0; i<size; ++i)
result[i] = std::make_unique<T>(std::forward<T>(data[i]));
return result;
}
結果向量現在擁有該數組,從某種意義上說,它存儲指向其元素的指針,並確保在向量被銷毀時刪除對象,但原始數組在此過程中失效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.