2013-03-05 70 views
2

我正在使用一種API,它在內存中提供了感興趣的字符串的內存地址和長度。我想將這些字符串讀入像wstring這樣的更友好的對象。將memcpy轉換爲向量<wchar_t>來自原始內存位置

對於較小的字符串,靜態大小的緩衝區工作正常使用下面的代碼:

// This code works (but may have other issues) 
// _stringLengthOffset and _bufferOffset are provided earlier by the API 
// stringOID is the memory location of the string (and in terms of the API, the ObjectID) 
DWORD stringLength; 
memcpy(&stringLength, ((const void *)(stringOID + _stringLengthOffset)), sizeof(DWORD)); 
wchar_t argString[DEFAULT_ARGVALUE_BUFFER_SIZE]; 
memcpy(argString, ((const void *)(stringOID + _bufferOffset)), (stringLength) * sizeof(wchar_t)); 
argString[stringLength] = L'\0'; // Strings are not null terminated in memory 
wstring argumentValue = argString; 



我不認爲這是建立一個非常,非常大的靜態大小的緩衝區是一個好主意(這些字符串可能有20000個或更多字符。)我嘗試了幾種不同的方法,並且這段代碼似乎很接近但不起作用。

// This code does NOT work. 
vector<wchar_t> buffer; 
buffer.reserve(stringLength + 1); 
memcpy(&buffer[0], (const void *)(stringOID + _bufferOffset), (stringLength) * sizeof(wchar_t)); 
buffer.push_back(L'\0'); 
buffer.shrink_to_fit(); 
wstring argumentValue(buffer.begin(), buffer.end()); 

問題:如果我們的目標是創造一個wstring的,如何正確地一個從原始內存(由這個特定的API提供)複製到一個動態大小的緩衝區,然後創建一個wstring的?道歉,如果這已經回答過了,因爲它看起來像是有人在我之前就問,但我無法找到一個合適的問題/答案與搜索了幾個小時。

回答

4

有很多方法。

1)使用resize而不是reserve,並執行memcpy。也擺脫了縮水配合。

2)直接指定到字符串:

const wchar_t* pstr = reinterpret_cast<const wchar_t*>(stringOID + _bufferOffset); 
wstring s(pstr, pstr + stringLength); 
// or: 
wstring s(pstr, stringLength); 

選項2)避免了調整載體的拷貝,並且另外的初始化。

+0

謝謝!這工作。順便說一句,memcpy對靜態大小的緩衝區有多大好處,而不是總是使用「wstring s(pstr,stringLength);」?我猜測現代編譯器沒有,因爲我們最終會使用一個wstring。 – 2013-03-06 00:25:00

+0

本質上,wstring構造將採取數據的副本,以便複製到中間數組是浪費精力。 根據std :: basic_string的實現(即,如果它在內部使用memcpy來處理POD字符類型),直接將memcpy直接寫入未初始化的內存中可能比使用wchar_t *構造字符串更快。 memcpy往往被高度優化(例如,使用SIMD指令或塊移動指令)。另外,你需要支付在堆中分配wstring的內部緩衝區,這比堆棧分配慢。 – Pete 2013-03-06 09:26:53

+0

除非此代碼對性能至關重要,否則我不會擔心。如果優化,通常只有一小部分程序對總體性能有任何影響。 – Pete 2013-03-06 09:28:36

2
std::wstring foo (somebuffer, charactercount); 

保留不會使向量x wchar_t的長。它只是預分配。該矢量仍然認​​爲它裏面有0項。當你調用push_back時,vector現在包含1個字符。 shrink_to_fit會將它留在1個字符處。 memcpy無法告訴該向量在複製後多久。我建議使用上面的答案,但如果你想要使用矢量,它會調整大小,而不是保留。不要做+1。這將在push_back中處理。

+0

有了你的代碼,如果'somebuffer'被釋放了什麼行爲? 'foo'的狀態是什麼? – Mic 2013-03-05 20:40:22

+0

foo包含在構造函數中創建的以NULL結尾的副本 – cppguy 2013-03-05 22:16:31

+0

那麼COW和所有這些東西呢? COW僅用於從現有的其他'std :: wstring'進行復制嗎? – Mic 2013-03-05 22:17:49