2014-07-09 11 views
0

나는 COW가 어떻게 작동하는지 이해하려고 노력하고 있는데, 나는 wikibooks에서 클래스를 찾았지만이 코드를 이해하지 못한다.적절한 사용법에 따라 복사 하시겠습니까?

template <class T> 
class CowPtr 
{ 
    public: 
     typedef boost::shared_ptr<T> RefPtr; 

    private: 
     RefPtr m_sp; 

     void detach() 
     { 
      T* tmp = m_sp.get(); 
      if(!(tmp == 0 || m_sp.unique())) { 
       m_sp = RefPtr(new T(*tmp)); 
      } 
     } 

    public: 
     CowPtr(T* t) 
      : m_sp(t) 
     {} 
     CowPtr(const RefPtr& refptr) 
      : m_sp(refptr) 
     {} 
     CowPtr(const CowPtr& cowptr) 
      : m_sp(cowptr.m_sp) 
     {} 
     CowPtr& operator=(const CowPtr& rhs) 
     { 
      m_sp = rhs.m_sp; // no need to check for self-assignment with boost::shared_ptr 
      return *this; 
     } 
     const T& operator*() const 
     { 
      return *m_sp; 
     } 
     T& operator*() 
     { 
      detach(); 
      return *m_sp; 
     } 
     const T* operator->() const 
     { 
      return m_sp.operator->(); 
     } 
     T* operator->() 
     { 
      detach(); 
      return m_sp.operator->(); 
     } 
}; 

그리고이 정보는 공유되는 맵 객체의 다중 스레드 응용 프로그램에서 사용됩니다.

map<unsigned int, LPOBJECT> map; 

그래서 템플릿을 할당했고 지금은이 :

CowPtr<map<unsigned int, LPOBJECT>> map; 

그리고 지금 내 질문 : 나는 propertly 임의의 맵의 인스턴스를해야하는 방법

  1. 스레드는 단지지도 객체를 읽으려고합니까?

  2. 지도 객체를 임의 스레드에서 수정해야하는 방법 (예 : 새 개체를 삽입하거나 지우시겠습니까?

답변

4

게시하는 코드는 사용하기가 어려울 정도로 가난합니다. 작성자가 const이 C++에서 작동하는 방식을 이해하지 못하는 것 같습니다.

실질적으로 말하기 : 암소 클래스에서 수행되는 작업에 대한 약간의 지식이 필요합니다. CoW 랩퍼는 랩된 오브젝트의 조작이 일 때 사본을 트리거해야합니다. 경우에 랩 된 객체는 또한 아무것도 되어 유출되면 전체 복사를 요구하는이 암기 할 수있는 "누설"포인터 또는 수정을 허용 반복자를 가지고 할 수있는. 게시 한 코드는 에 따라 복사본을 트리거합니다. 포인터가 const인지 아닌지는 전혀 같지 않습니다. 것입니다. 따라서, 에 std::map<>::find를 호출 std::map와지도해야 하지 트리거 포인터 이 CONST없는 경우에도 쓰기 복사, 및 호출 std::map<>::insert, 경우에도 포인터가 const를이해야한다. 스레딩 관련하여

: 그것은 실제 객체가 스레드간에 공유 할 때 알아야하는 것은 매우 어렵 기 때문에, 돌연변이 수있는 모든 작업을 에 대한 잠금을 잡아없이 소 클래스는 스레드로부터 안전하기 위해 매우 어렵습니다. 심지어 객체가 포인터 또는 반복기를 허용하는 경우에도 더 어려워 표준 라이브러리 객체처럼 누출됩니다. 당신이 스레드 안전 암소지도를하려는 이유

당신은 설명하지 않습니다. 지도의 점은 무엇인지를 추가하거나 다른 경우에 표시되지 않는 새 복사본으로 결국 , 요소를 제거 할 때마다? 그것의 경우 단지 일부 기존지도의 사본을 개별 인스턴스를 시작, std::map은 잘 작업을 수행하는 복사 생성자 을 가지고 있으며, 당신은 어떤 공상 래퍼가 필요하지 않습니다.

1

어떻게 작동합니까?

클래스 class CowPtr에는 기본 객체에 대한 공유 포인터가 있습니다. 새로운 객체를 복사하고 로컬 공유 포인터에 포인터를 할당하는 개인 메소드가 있습니다 (다른 객체가 참조를 보유하고있는 경우) : void detach().

코드의 관련 부분은

const return_type& 
method_name() const 

한번 CONST없이 같은 각각의 방법을 가지고있다. 메소드가 객체를 수정하지 않는다는 것을 보장 한 후에 메소드는 const 메소드이라고 불린다. 기본 객체에 대한 참조가 const이기 때문에 참조를 수정할 필요가 없을 때마다 해당 메소드가 호출됩니다.

경우 예를 들어, 참조 뒤에 개체를 수정하기로 결정했습니다 그러나 :

CowPtr<std::map<unsigned int, LPOBJECT>> map; 
map->clear(); 

detach()를 호출 T& operator->()가 호출되는 const가 아닌 방법. 그렇게함으로써, 사본은 다른 CowPtr 또는 shared_ptr는 동일한 기본 객체 (이 경우 <unsigned int, LPOBJECT>의 인스턴스)

를 참조하고 어떻게 그것을 사용하려고 시도하는?

std::shared_ptr 또는 boost::shared_ptr을 어떻게 사용 하시겠습니까? 그 구현에 대한 멋진 점은 모든 것을 자동으로 처리한다는 것입니다.

비고 사본 당신은 당신이 -Implementation를 작성하지 않는 것을 보장하지 않는 경우가 더 복사하고, 쓰지 않아도된다 이것은하지만 더 COW 없습니다.

+0

게시 된 코드가 작동하지 않는다는 점을 제외하고는 복사 여부를 결정하는 데 사용되는 constness가 포인터가 가리키는 포인터가 아니기 때문에. 따라서'CoWPtr const &'를 객체를 수정할 수있는 함수에 전달할 수는 없지만 비 const 포인터에서 const 함수를 호출하면 복사가 수행됩니다. –

+0

@JamesKanze 네, 그게 "당신이 쓰기를하지 않는다고 보장하지 않으면 복사하십시오."입니다. 나는 네 자신에게 "이 구현이 좋은가?"라고 묻지 않았기 때문에 당신의 대답을 반대했다. 오히려 "어떻게 그 일을 설명 할 수 있니?" ;) – Theolodis