2012-09-21 3 views
0

모든 CopyMemory 함수를 std :: copy 함수로 변환하려고합니다.메모리를 std :: copy로 복사하십시오.

copymemory 및 memcpy에서는 작동하지만 std :: copy에서는 작동하지 않습니다. 누구든지 내가 뭘 잘못하고 어떻게 해결할 지 말해 줄 수 있니?

std::string Foo = "fdsgsdgs"; 

std::string::iterator it = Foo.begin(); 

unsigned char* pt = &(*it); 

어떻게 다음 반복자 포인터를 변환합니다 :

template<typename T> 
void S(unsigned char* &Destination, const T &Source) 
{ 
    //CopyMemory(Destination, &Source, sizeof(T)); 
    std::copy(&Source, &Source + sizeof(T), Destination);  //Fails.. 
    Destination += sizeof(T); 
} 

template<typename T> 
void D(T* &Destination, unsigned char* Source, size_t Size) 
{ 
    //CopyMemory(Destination, Source, Size); 
    std::copy(Source, Source + Size, Destination); 
    Source += sizeof(T); 
} 

template<typename T> 
void D(T &Destination, unsigned char* Source, size_t Size) 
{ 
    //CopyMemory(&Destination, Source, Size); 
    std::copy(Source, Source + Size, &Destination); 
    Source += sizeof(T); 
} 

나는 또한 내가 할 수있는 포인터로 반복자를 변환하려면 다음을 냈어요? : S

내가 (그렇지 않은 경우 작동하는 경우 7 인쇄 ... 랜덤 숫자)을 방어 적이기/표준 대 copymem :: 다음과 같이 복사가됩니다를 테스트하는 데 사용하는 코드 :

#include <windows.h> 
#include <iostream> 
#include <vector> 
#include <typeinfo> 

using namespace std; 

typedef struct 
{ 
    int SX, SY; 
    uint32_t Stride; 
    unsigned long ID; 
    int TriangleCount; 
} Model; 

template<typename T> 
void S(unsigned char* &Destination, const T &Source) 
{ 
    CopyMemory(Destination, &Source, sizeof(T)); 
    Destination += sizeof(T); 
} 

template<typename T> 
void S(unsigned char* &Destination, const std::vector<T> &VectorContainer) 
{ 
    size_t Size = VectorContainer.size(); 
    for (size_t I = 0; I < Size; ++I) 
     S(Destination, VectorContainer[I]); 
} 

void S(unsigned char* &Destination, const Model &M) 
{ 
    S(Destination, M.SX); 
    S(Destination, M.SY); 
    S(Destination, M.Stride); 
    S(Destination, M.ID); 
    S(Destination, M.TriangleCount); 
} 

template<typename T> 
void D(T* &Destination, unsigned char* Source, size_t Size) 
{ 
    CopyMemory(Destination, Source, Size); 
    Source += sizeof(T); 
} 

template<typename T> 
void D(T &Destination, unsigned char* Source, size_t Size) 
{ 
    CopyMemory(&Destination, Source, Size); 
    Source += sizeof(T); 
} 

template<typename T> 
void D(std::vector<T> &Destination, unsigned char* Source, size_t Size) 
{ 
    Destination.resize(Size); 
    for(size_t I = 0; I < Size; ++I) 
    { 
     D(Destination[I], Source, sizeof(T)); 
     Source += sizeof(T); 
    } 
} 

void D(Model* &Destination, unsigned char* Source) 
{ 
    D(Destination->SX, Source, sizeof(Destination->SX)); 
    D(Destination->SY, Source, sizeof(Destination->SY)); 
    D(Destination->Stride, Source, sizeof(Destination->Stride)); 
    D(Destination->ID, Source, sizeof(Destination->ID)); 
    D(Destination->TriangleCount, Source, sizeof(Destination->TriangleCount)); 
} 

long double* LD = new long double[25000]; 
std::vector<Model> ListOfModels, ListOfData; 

void ExecuteCommands() 
{ 
    switch(static_cast<int>(LD[1])) 
    { 
     case 1: 
     { 
      LD[2] = 2; 
      unsigned char* Data = reinterpret_cast<unsigned char*>(&LD[3]); 
      Model M; M.SX = 1; M.SY = 3; M.Stride = 24; M.ID = 7; M.TriangleCount = 9; 
      Model K; K.SX = 3; K.SY = 21; K.Stride = 34; K.ID = 9; K.TriangleCount = 28; 

      ListOfModels.push_back(M); 
      ListOfModels.push_back(K); 
      S(Data, ListOfModels); 
     } 
     break; 
    } 
} 

void* GetData() 
{ 
    unsigned char* Data = reinterpret_cast<unsigned char*>(&LD[3]); 
    D(ListOfData, Data, LD[2]); 
    cout<<ListOfData[0].ID;  //Should print 7 if it works. 
    return &ListOfData[0]; 
} 


int main() 
{ 
    LD[1] = 1; 
    ExecuteCommands(); 
    GetData(); 
} 
+1

[RTFM] (http://www.cplusplus.com/reference/algorithm/copy/) : 대상은 출력 반복자 여야합니다. –

+0

흠, 반복기가 없으므로 사용할 수 없습니다. : SI는 memcpy를 계속 사용합니다. – Brandon

+2

오류가 발생했습니다. 당신이 소스 코드 또는 대상 타입을 templatize한다는 것만 제외하면 코드에 대한 유일한 괴상한 사실이 있습니다. 그러나 타입이 일치하지 않으면 std : : 복사본은 유형에 대해 안전합니다. – user1610015

답변

8

이 코드에는 여러 가지 문제가 있으므로 어디서부터 시작해야할지 모르는 것이 거의 없습니다. 그리고 오류는 많은 경우에있어서 당신이해야 할 일에 대한 큰 오해를 배제하기 때문에 기본적입니다. 당신이 작성한 코드 종류는 숙련 된 C++ 프로그래머에게는 위험합니다. 코드에서 작성한 오류로 인해 경험이 많이 떨어진다는 것을 알 수 있습니다.

당신이하려는 일을 중단하십시오.

하지만 코드를 작성해 보겠습니다.

std::copy(&Source, &Source + sizeof(T), Destination);  //Fails.. 

먼저 C++에서 포인터에 대해 설명하겠습니다.

당신이 어떤 종류의 T에 대한 포인터가있는 경우의 일, T *t을 가정 해 봅시다이 t + 1 것이다 하지 이동 한 바이트 위에 포인터. 여기는 기본적인 포인터 연산입니다. t + 1sizeof(T)에 의해 그것을 옮길 것입니다; 포인터가 C의 초기부터 어떻게 작동했는지, C++은 말할 것도 없습니다.

SourceT&이므로 &SourceT*입니다. 따라서 sizeof(T)을 추가하면 포인터가 sizeof(T) * sizeof(T)만큼 증가합니다. 그것은 당신이 원하는 것이 아닙니다.

둘째, std::copy은 memcpy이 아닙니다. std::copy은 하나의 값 콜렉션 (입력 반복자 쌍에 의해 정의 됨)을 출력 반복자에 의해 정의 된 다른 값 콜렉션으로 복사하기위한 것입니다. std::copy은 입력 반복자의 value_type이 출력 반복자의 value_type으로 암시 적으로 변환 가능해야합니다.

해당 입력 반복기 인 T*value_typeT입니다. T* 님의 포인터가 T입니다. 출력 반복자 인 char*value_typechar입니다. std::copy은 효과적으로 수행하려고 할 것입니다 :

char *val; 
T *t; 
*val = *t; 

에도이 두 포인터가 초기화되지 않은 사실을 무시

이는 이해되지 않는다. Toperator char 변환 연산자가없는 경우 T을 입력하고 char으로 이동하면됩니다.따라서 컴파일 오류가 발생합니다. 너도 그래야 해.

T이 실제로 있고 적절한 크기의 char* 배열로 복사하려는 경우 (또는 그 반대) std::copy은 필요한 도구가 아닙니다. 원하는 도구는 std::memcpy입니다. std::copy개체 인을 복사하기위한 것으로 바이트를 복사하지 않습니다.

+0

위대한 답변이지만 위의 답을 원합니다.'std :: copy (reinterpret_cast (& t), reinterpret_cast (& t) + sizeof (t), dest)'가이 용도로 사용됩니다. ;) – Xeo

+0

@ Xeo : 매번 'reinterpret_cast'가 눈에 상처를줍니다. 그 외에 *는이 목적을 위해 작동합니다 *은 매우 대담한 성명입니다. 실제로 작동하지 않는 몇 가지 유형의 'T'를 제공 할 수 있습니다 (실제 표준 레이아웃 유형이 아닌 경우). 그 외에도,'memcpy'를 사용하려고한다면'memcpy'를 사용하십시오. 코드에서 적어도 많은 유형에 잠재적으로 위험한 일을하고 있다는 것은 분명합니다. 'std :: copy'의 관점에서'memcpy'를 작성해도 덜 위험하지 않으며, 더럽 히고 (잠재적으로 더 느리게) 만듭니다. –

+0

@David : 죄송합니다. 끝에 ";)"는 대부분 혀가 뺨에 농담으로되어 있다는 것을 분명히했습니다. 물론 이것은 단지 문제를 일으킨다는 것을 알고 있습니다. :) – Xeo

관련 문제