2010-03-31 3 views
3

값으로 전달되지만 형식 정보를 유지 관리하지 않는 범용 데이터 형식이 있습니다. 우리는이 안에 포인터와 기본 데이터 유형 (int, float 등) 만 저장합니다. 이제 처음으로 std :: string을이 안에 저장해야합니다. 그래서 우리는 이것을 std :: string *으로 변환하여 저장하기로 결정했습니다. 그러면 파멸의 문제가 온다. 우리는 std :: string을 매번 복사하는 것을 싫어합니다. 그래서 나는 이런 접근 방식을 생각하고 있습니다. 이 성병 더 이상 참조 : 문자열 *이 없는지를 확인하는 좋은 방법입니다 데이터 유형이C++ 범용 데이터 형식

class Atom 
{ 
public : 
    enum flags 
    { 
     IS_STRING, 
     IS_EMPTY, 
     HAS_GOT_COPIED, 

     MARKER 
    }; 

private: 
    void* m_value; 
    std::bitset<MARKER> m_flags; 

public: 
    ..... 
    Atom(Atom& atm) 
    { 
     atm.m_flags.set(HAS_GOT_COPIED); 
     ..... 
    } 
    ..... 
    ~Atom() 
    { 
     if(m_flags.test(IS_STRING) && !m_flags.test(HAS_GOT_COPIED)) 
     { 
      std::string* val = static_cast<std::string*>(m_value); 
      delete val; 
     } 
    } 
}; 

과 같은 말? 모든 의견 ..

나는 boost :: any와 poco :: DynamicAny를 보았다. 직렬화가 필요하기 때문에 사용할 수 없습니다.

고마워, 고쿨.

+1

당신은 boost :: variant를 보았습니까? 직렬화가 boost :: any의 사용에 어떤 영향을 미칩니 까? (나는 결코 poco : : DynamicAny를 시도한 적이 없다) –

+1

템플릿에 포함 할 객체 유형에 Atom 템플릿을 사용하는 이유는 무엇입니까? –

+0

@ George : 그것은 하나의 데이터 유형이 아니며 목적을 달성하지 못합니다. – Gokul

답변

4

이 접근법의 한 가지 주요 결함은 정말 참조 카운트가 아니라 단일 비트 "복사되었습니다"플래그가 필요합니다. 문자열을 여러 번 복사하면 비트가 작동하지 않습니다. 기록으로, 당신은 당신이 Atom의 사본을 만들 경우 곤경에 얻을 원래 전에 사본을 삭제합니다 :

Atom a("hello world"); 

if (...) { 
    Atom b(a); 
    // b is destroyed, deleting the string 
} 

// Uh oh, the string's been deleted but a is still referencing it. 
cout << (string) a; 

나는 바퀴를 다시 발명하지 않을 것입니다. boost::any 상자가 작동하지 않으면 Atom 클래스의 데이터를 저장하기 위해 m_value 필드 대신 내부적으로 사용할 수 있습니다. 그러면 모든 건설/복사/파괴 세부 사항이 처리됩니다.

+0

고마워. 내가 문제가있어. 하지만 부스트 직렬화를 지원하지 않기 때문에 나는 boost :: any를 사용할 수 없다. – Gokul

+1

클래스에 직렬화를 추가하고 내부적으로 boost :: any 또는 boost :: variant를 사용할 수있다. –

+0

@David : 나는 boost :: any의 비용을 지불하고 싶지 않습니다. type_info를 void *로 변환 한 다음 boost :: any에 저장하면 안됩니다. 현재 바이트 길이의 스트림으로 데이터를 가져와 직렬화 중입니다. – Gokul

4

나는 boost :: shared_ptr (또는 std :: tr1 :: shared_ptr)을 사용할 가능성을 조사해야한다고 생각한다.

+0

이것은 전달 값 데이터 유형입니다. 귀하의 제안은 참조 데이터 유형에 의한 통과에 유효하다고 생각합니다. – Gokul

+0

그의 제안은 copyable, pass-by-value 클래스에 좋습니다. copy-by-reference 타입은 복사 문제가 없습니다. –

+1

나는 shared_ptr을 사용하여 std :: string *을 추적하고 적절한 순간에 할당을 해제하려고했습니다. std :: string을 포함하는 Atom이 여러 번 복사되고 원래 인스턴스의 수명이 가장 긴 경우 어떻게 처리할까요? –

3

"copy on write"를 Google에 제공하고 해당 주제를 읽으십시오. 그것이 일반적으로 어떻게 구현되고, 어떤 용도로 사용되며, 단점은 무엇입니까.

그리고 boost::any을 보셨습니까?

+0

예, boost :: any를 보았습니다. 여기에 직렬화가 필요하기 때문에 여기서는 사용할 수 없습니다. – Gokul

+0

@Gokul : 귀하의 유형이 무료로 직렬화와 함께 제공되는 것처럼 아닙니다. 직접 구현해야합니다. 당신이'boost : any'에 기초를 둔다면, 적어도 당신은 견고한 토대를 가졌습니다. – sbi

1

이러한 종류의 '범용 데이터 형식'이 좋은 아이디어인지 여부와는 별도로 문자열을 복사하지 않으면이 클래스는 포인터가있는 문자열을 소유하고 있는지 확인할 수 있습니까? 소유권을 얻기 위해 new을 통해 할당 된 문자열 만 클래스에 전달 될 것이라고 보장 할 수 있습니까?

이 클래스의 디자인은 문제가있는 것처럼 보입니다.

+0

네, 그 생성자와 set 문은 없습니다. – Gokul

+0

@ 고킬 - 그건별로 문제가되지 않습니다. 생성자를 호출하는 사람은'new '를 통해 할당 된 문자열로만 호출하고 호출자는 문자열에서'delete'를 호출하지 않을 것이라고 확신 할 수 있습니까? 이러한 규칙은 디자인을 적용하기가 어려울 수 있으므로 그러한 디자인을하기 전에 생각 해보는 것이 좋습니다. –

+0

미안하지만, 그것에 대해 언급하지 않았지만, 사람들은 단지 std :: string으로 전달할 것이고 std :: string *으로 변환 할 것입니다. 그래서 나는 그것을 풀어 줄 필요가있다. std :: string *으로 전달 된 경우에는 해제하는 것에 대해 걱정할 필요가 없습니다. – Gokul

2

첫 번째 작업에서 내 첫 번째 작업 중 하나는 변형 클래스를 디자인하는 것이 었습니다. 여기에 comp.lang.c++.moderated post에서 몇 가지 기본 코드 (및 토론)를 찾을 수 있습니다.

일련 번호가 필요하기 때문에 JsonCpp 라이브러리에 관심이있을 수 있습니다. 문자열, 부울, int, 배열, 객체 등일 수있는 데이터 유형 (Json::Value 클래스)을 제공한다고 생각합니다.

+0

감사합니다 !! 제가 확인하겠습니다. – Gokul

+0

낯선 사람, 당신이 downvoting 때 설명 해주십시오 :) – StackedCrooked