2014-01-28 3 views
0

이 같은 코드를보고 뭔가가 있습니다부스트 직렬화

struct DataStruct 
{ 
// some fields here 
}; 

class C1 
{ 
public: 
    C1(size_t n) 
    { 
     ptrData = new DataStruct[n]; 
     ptrPtrs = new DataStruct*[n]; 
     for(size_t i=0;i<n;i++) 
      ptrPtrs[i] = &ptrData[i]; 
    } 

    virtual ~C1() 
    { 
     delete[] ptrData; 
     delete[] ptrPtrs; 
    } 

    DataStruct* ptrData; 
    DataStruct** ptrPtrs; 
}; 

을하고 부스트 :: 직렬화 바람직 직렬화 할 필요가있다. 루프에서 항목별로 항목을 저장하는 것 외에 동적으로 할당 된 배열을 저장하는 방법을 찾지 못했습니다. 그러나 두 번째 배열 - 포인터 배열을 저장하는 방법을 모릅니다. 그것은 부스트에서 더 많거나 적은 편리하게 할 수 있습니까?

답변

2

부스트는 요소 수를 포인터로 알고 있기 때문에 불가능합니다. 힙 관리자는 delete []를 호출 할 때 삭제할 요소 수를 알고 있지만 boost::serialize

등의 코드를 사용할 수 없습니다. 물론 가장 좋은 방법은 std::vector을 사용하는 것이지만 실패하면 직렬화에 사용할 수있는 인바운드 및 아웃 바운드 "래퍼"클래스입니다.

우리가 ArrayWrapper를 호출하고

template< typename T > 
struct ArrayWrapper 
{ 
    T* data = nullptr; 
    size_t size = 0; 
    ArrayWrapper() = default; 
    ArrayWrapper(T* data_, size_t size_) : data(data_), size(size_) {} 
}; 

이제 먼저, 다음 각 항목을 크기를 작성하여 포인터 및 알려진 크기에서 하나를 직렬화 할 수 템플릿합니다. 다시 직렬화 할 때

, 당신은 먼저 개체의 수를 할당 한 다음 메모리를 관리 할 필요가 물론

. 그들을 읽고 std::vector이 훨씬 더 나은 옵션 사용하여 크기를 참조하십시오.

일반적으로 포인터가 가리키는 데이터를 저장하는 "포인터"는 저장하지 마십시오. 아카이브에서 다시 읽어 들일 때 동일한 포인터를 가져 오지 않으면 동일한 데이터를 다시 얻을 수 있습니다.

그런 목적을 위해, 실제로는 바깥 쪽 포인터 (포인터의 배열)를 저장하고 안쪽에 ArrayWrapper를 호출하도록합니다.

+0

음, 직렬화에 위의 대답과 같이 배열 길이를 지정할 수있는 일종의 어댑터가 있기를 바랍니다. 벡터는 옵션이 아닙니다. 왜냐하면 어떤 요소가 내부적으로 이동되지 않을지 보장하지 않기 때문에 벡터 항목에 대한 포인터를 저장할 수 없기 때문입니다. – ilya

+0

어떤 식 으로든 벡터의 크기를 수정하지 않으면 벡터 요소가 이동하지 않으며, 앞쪽으로 예약하면 이동하지 않습니다. – CashCow

+0

스마트 포인터의 벡터를 저장할 수도 있습니다. 벡터의 요소가 이동하더라도 포인터가 가리키는 항목은 표시되지 않으며 스마트 포인터는 유효합니다. 이 경우 shared_ptr을 사용할 수 있으며주의해야한다면 unique_ptr은 사용할 수 있지만 auto_ptr은 사용할 수 없습니다. – CashCow