Я работаю с API, который предоставляет в памяти адрес памяти и длину интересующих строк. Я хотел бы прочитать эти строки в более дружественные объекты, такие как wstring.
Для небольших строк буфер статического размера работает нормально, используя следующий код:
// 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;
Я не думаю, что было бы хорошей идеей создать очень большой буфер статического размера (с этими строками возможно 20 000 символов или более). Я пробовал несколько разных подходов, и этот код кажется близким, но НЕ работает.
// 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?
(Извиняюсь, если на этот вопрос уже был дан ответ, так как кажется, что кто-то до меня бы спросил, но я не смог найти подходящий вопрос / ответ за несколько часов поиска.)
Есть несколько способов.
1) Используйте resize вместо резерва и сделайте memcpy. также избавиться от усадки.
2) Назначить непосредственно на строку:
const wchar_t* pstr = reinterpret_cast<const wchar_t*>(stringOID + _bufferOffset);
wstring s(pstr, pstr + stringLength);
// or:
wstring s(pstr, stringLength);
Вариант 2) позволяет избежать копирования и дополнительной инициализации измененного вектора.
std::wstring foo (somebuffer, charactercount);
Запас не делает вектор х wchar_t длинным. это просто распределяет. вектор все еще думает, что внутри него 0 элементов. когда вы вызываете push_back, вектор теперь содержит 1 символ. shrink_to_fit оставит это в 1 символе. memcpy не может сказать вектору, сколько времени пройдет после копирования. Я бы рекомендовал использовать ответ выше, но если вы одержимы использованием вектора, это изменение размера, а не резервирование. и не делай +1. Это будет обработано в push_back.