2017-11-11 284 views
3

給定一個原始數組元素,如何創建一個std::vector,該數組獲取原始數組的所有權而不用重新分配& copy?從原始數據創建std :: vector

例如具有原始陣列:

int* elems = new int[33]

如何創建尺寸33指向elemsstd::vector

我相信理論上這是可能的,因爲通常std::vector被實現爲包含三個指針的結構,一個指向分配內存的開始,一個指向有效元素的末尾,一個指向有效元素的末尾,一個指向末尾分配的內存。但有沒有一種標準的方式來初始化原始數組的std::vector結構?

+5

你不能。不要使用新的「原始數據」,使用矢量。 – 2017-11-11 09:04:48

+2

如果你需要像'begin'或'front'這樣的常用方法,你可以在'unique_ptr '中存儲指向數組的指針並通過'array_view '訪問數組內容。 – VTT

+1

做相反的事情:讓'vector'管理內存,並創建一個指向它的指針'std :: vector v; int * elems = v.data();' – Tas

回答

1

根據this,沒有構造函數接受指向數據的指針。所以,你不能將原始數組的所有權傳遞給vector。

您只能創建一個向量並將數據放入其中。

+0

我知道根據引用的來源,沒有辦法做到這一點,但你不覺得這是可能的和有用的,這應該有可能做到這一點? – cDc

+1

@cDc矢量如何安全地獲取指針的所有權?沒有辦法將它限制爲動態分配的指針。 – user0042

+0

不確定你的意思;通過擁有所有權,我的意思是'elems'變量不會在'std :: vector'創建後被使用,並且數組的所有管理都將通過'std :: vector'方法完成,包括添加/刪除元素。 – cDc

2

這不是直接可能的原因是標準庫使用分配器爲容器保留內存。

因此,如果你有一個std::vector它使用某種類型的分配器,並給它一些你創建的指針,你會有效地打破分配器的習慣用法。如果您的標準庫的實現例如使用mallocfree而不是newdelete,則程序將失敗。

對於這個成爲標準方式,標準庫需要提供接受其還必須已經由矢量後使用相同的分配器返回T*構造。所以你需要的構造函數的簽名就像std::vector::vector(T* data, size_type used_elements, size_type capacity, const Allocator& alloc)。請注意,allocator參數是必需的,因爲T*必須(理論上)由向量中使用的完全相同的分配器返回。


您可以通過創建根據this concept你自己的分配器實現 一些功能 這一點,但有你的33元素無法重建你還必須提供一個allocator::construct(..)功能是無糖op直到34th元素(不包括)。此外,您必須首先將矢量調整爲33元素,以強制矢量具有正確的大小。

這是說這不過是一個壞主意,因爲對於條件構造和分配函數,您可能會有更多的開銷,而不是複製一次元素。

+0

的'的std :: VECTOR'聲明是 '''模板< 類T, 類分配器=標準::分配器 >類矢量; ''' 所以創建的向量可以伴隨正確的分配器,包括'malloc'和'free' – cDc

+1

@cDc是的,但不幸的是我不知道你想告訴我這個.. – nyronium

+0

@nyronium我認爲你*可以*寫一個合法的分配器來完成OP所需要的;分配器會檢查T *和它的初始化大小是否與競技場內存相匹配,並將分配和構造變成幾乎沒有操作(當然,分配器仍然會複製增長)... –

3

你需要的是一個「視圖」而不是一個容器。容器擁有自己的元素,其主要目的是封裝他們管理的原始記憶。如果你需要自己管理內存,那麼你不需要容器。看看string_view這將是你的解決方案,如果你有一個string。也許boost ranges是你可以應用的東西。從文檔(強調雷):

的範圍概念的動機是,有一些可以與寫了很多有用的集裝箱般 類型不符合 集裝箱的全部要求,很多算法這減少了 一組要求。特別是,範圍並不一定

  • 擁有可以通過它訪問的元素,
  • 有複製語義,

PS:其實std::array_view被認爲是C + +17,但不幸的是它並沒有成爲標準。

+0

'std :: array_view'沒有把它變成C++ 17。 –

+0

@ChristianHackl thx,已更新 – user463035818

0

鑑於原始的排列要素,如何創建一個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>

0

如果你正在使用的對象的類型是可移動的,你可以這樣做:

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; 
} 

所產生的載體現已擁有陣列,因爲它存儲指向它的元素,並確保感當向量被銷燬時對象被刪除,但原始數組在過程中被取消。