![](/img/trans.png)
[英]How to convert std::vector<unsigned char> to vector<char> without copying?
[英]Can I reinterpret std::vector<char> as a std::vector<unsigned char> without copying?
我有一個std::vector<char>
的引用,我想用它作為接受std::vector<unsigned char>
的函數的參數。 我可以不復制嗎?
我有以下功能,它的工作原理; 但我不確定副本是否真的發生 - 有人可以幫助我理解這個嗎? 是否可以使用std::move
來避免復制或者它是否已被復制?
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
char* buf = chunkdata.data();
unsigned char* membuf = reinterpret_cast<unsigned char*>(buf);
std::vector<unsigned char> vec(membuf, membuf + chunkdata.size());
showDataBlock(usefold, usecolor, vec);
}
我以為我可以寫:
std::vector<unsigned char> vec(std::move(membuf),
std::move(membuf) + chunkdata.size());
這有點矯枉過正嗎? 究竟發生了什么?
...是否可以使用std :: move來避免復制,或者它是否已被復制
您不能在兩個不相關的容器之間移動。 std::vector<char>
不是 std::vector<unsigned char>
。 因此,沒有合法的方法在O(1)時間內將一個內容“移動〜轉換”到另一個內容。
你可以復制:
void showData( std::vector<char>& data){
std::vector<unsigned char> udata(data.begin(), data.end());
for(auto& x : udata)
modify( x );
....
}
或者為每次訪問實時投射......
inline unsigned char& as_uchar(char& ch){
return reinterpret_cast<unsigned char&>(ch);
}
void showDataBlock(std::vector<char>& data){
for(auto& x : data){
modify( as_uchar(x) );
}
}
我猜你編碼了另一個重載函數: -
showDataBlock(usefold, usecolor, std::vector<unsigned char> & vec);
您嘗試從std::vector<T>
轉換為另一個std::vector<T2>
。
沒有辦法避免復制 。
每個std::vector
都有自己的存儲空間,粗略地講,它是一個原始指針。
重點是:你不能在多個std::vector
共享這樣的原始指針。
我認為這是設計的。
我認為這是一件好事,否則會浪費CPU來跟蹤。
編碼 ...
std::move(membuf)
...移動原始指針=實際上什么都不做。 (與傳遞為membuf
相同)
要進行優化,您應該驗證原因:首先要將std::vector<char>
轉換為std::vector<unsigned char>
。
如果你創建一個可以表示char
和unsigned char
的新類C
,這是一個更好的主意嗎? (例如C::getChar()
和C::getUnsignedChar()
,可能是......只存儲char
但提供轉換器作為其非靜態函數)
如果它沒有幫助,我建議創建一個新的自定義數據結構。
我經常在需要時這樣做。
但是,在這種情況下,我認為不需要任何優化。
對我來說沒關系,除非它是性能關鍵代碼。
如果你有一個類型為std::vector<T1>
的v1
並且需要一個類型為std::vector<T2>
的v2
,那么即使T1和T2像char
和unsigned char
一樣“相似”,也無法復制數據。 。
使用標准庫:
std::vector<unsigned char> v2;
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));
唯一可行的方法是以某種方式只使用一種類型:如果可能的話,從一開始就獲取std::vector<T2>
,或者從現在開始使用std::vector<T1>
(可能會添加一個超載用它)。 或者創建可以處理任何[contigous]容器的通用代碼(模板)。
我認為reinterpret_cast和std :: move應該可以避免復制
不,它不能
請詳細說明 - 為什么不呢?
矢量可以僅從相同類型的另一個矢量中竊取資源(移動數據)。 這就是它的界面設計方式。
要做你想做的事,你需要一個release()方法,它將釋放底層數據的向量所有權並將其作為(唯一)指針和移動構造函數/賦值返回,它將從(唯一)指針獲取底層數據。 (即便如此,你仍然需要一個reinterpret_cast
,這是......危險區域)
std::vector
沒有這些。 也許應該有。 它只是沒有。
正如其他人已經指出的那樣,如果不改變showDataBlock
,就無法繞過副本。
我想你有兩個選擇:
showDataBlock
以處理signed char
和unsigned char
(即使其成為模板)或 value_type
為char
情況下)使用特殊迭代器從signed char
轉換為unsigned char
元素。 而unsigned char
和char
是不相關的類型。 我認為它們在這種情況下(相同大小的pod)足夠相似,以逃避整個模板類的reinterpret_cast。
static void showDataBlock(bool usefold, bool usecolor,
std::vector<char> &chunkdata)
{
showDataBlock(usefold, usecolor, reinterpret_cast< std::vector<unsigned char>&>(chunkdata));
}
但是,我傾向於發現這些問題是由於沒有設計出最好的架構。 看看這個軟件應該做的更大的圖片,以確定為什么你需要使用有符號和無符號的char數據塊。
我最終做了這樣的事情:
static void showDataBlock(bool usefold,bool usecolor, std::vector<char> chunkdata)
{
std::vector<unsigned char>&cache = reinterpret_cast<std::vector<unsigned char>&>(chunkdata);
showDataBlock(usefold, usecolor, cache);
}
static bool showDataBlock(bool usefold,bool usecolor, std::vector<unsigned char> &chunkdata)
{
// showing the data
}
這個解決方案允許我傳遞矢量作為參考或正常它似乎工作 - 如果它是我不知道的最佳解決方案,但是你們都帶來了一些非常好的建議 - 謝謝大家
我同意我無法避免副本,所以我讓副本通過正常參數傳遞完成
如果您發現此解決方案有誤,請在評論中提供更好的解決方案,而不僅僅是downvote
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.