2013-03-05 6 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; 



내가 (매우, 매우 큰 정적 크기의 버퍼를 생성 할 수있는 좋은 아이디어라고 생각하지 않습니다 작은 문자열에 대한

는 정적 크기의 버퍼는 다음 코드를 사용하여 잘 작동 이 문자열은 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을 만들? (나에게 질문을 것이다 그러나 나는이 검색의 몇 시간에 적절한 질문/답을 찾을 수 없습니다 전에 뭔가 다른 사람처럼 보인다 사과이 이전에 응답 한 경우.를)

답변

4

다양한 방법이 있습니다.

1) 예약 대신 크기 조정을 사용하고 memcpy를 수행하십시오. 또한 shrink fit을 제거하십시오.

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 (pstr, stringLength);"을 사용하고 있습니까? 우리는 어쨌든 끝에 wstring을 사용할 것이기 때문에 현대 컴파일러를 사용하지 않을 것이라고 생각합니다. –

+0

기본적으로 wstring 구조는 데이터 복사본을 가져 와서 중간 배열로 복사하는 것은 낭비입니다. std :: basic_string (즉, POD 문자 유형에 내부적으로 memcpy를 사용하는 경우)에 따라 wchar_t *를 사용하여 문자열을 생성하는 것보다 memcpy를 직접 초기화하지 않은 메모리에 직접 저장할 수 있습니다. memcpy는 고도로 최적화 된 경향이있다.SIMD 명령어 또는 블록 이동 명령어 사용). 또한 스택 할당보다 느린 힙에서 wstring의 내부 버퍼를 할당하는 비용을 지불합니다. – Pete

+0

이 코드가 성능에 중요하지 않다면 너무 걱정하지 않아도됩니다. 일반적으로 프로그램의 아주 작은 부분 만 최적화하면 전반적인 성능에 영향을 미칩니다. – Pete

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

reserve는 벡터 x wchar_t의 long을 만들지 않습니다. 그것은 단지 미리 할당됩니다. 벡터는 여전히 내부에 0 개의 항목이 있다고 생각합니다. push_back을 호출하면 벡터에 이제 1 문자가 포함됩니다. shrink_to_fit은 1 문자로 남겨 둡니다. memcpy는 복사 후에 얼마나 오래 될지 벡터에 알릴 수 없습니다. 위의 대답을 사용하는 것이 좋습니다 것이지만 벡터를 사용하는 것이 지긋 지긋한 경우 예약하지 않고 크기를 조정하십시오. +1하지 마세요. 그것은 push_back에서 처리 될 것입니다.

+0

코드에서 'somebuffer'가 할당 해제되면 어떤 행동을합니까? 'foo'의 상태는 무엇입니까? – Mic

+0

foo에는 생성자에서 생성 된 null로 끝나는 복사본이 포함되어 있습니다. – cppguy

+0

COW와 그 모든 것들은 어떻게됩니까? COW는 다른 기존의'std :: wstring'에서 복사 할 때만 사용합니까? – Mic