라이브러리 인터페이스에서 약한 _ptr에 대한 액세스를 제공하는 것이 현명합니까?

StackOverflow https://stackoverflow.com/questions/631380

  •  08-07-2019
  •  | 
  •  

문제

여러 관련 객체 유형에 대한 참조를 노출시키는 라이브러리를 작성했습니다. 이 모든 개체에는 내부적으로 라이브러리가 수명을 관리합니다. boost::shared_ptr

도서관 사용자는 또한 라이브러리의 본질적으로 노출 된 물체의 수명을 알 수 있습니다. 그래서 그들은 포인터를 저장하거나 이러한 물체에 대한 참조를 유지할 수 있습니다. 그들이 이것을 수행하고 그 객체가 더 이상 유효하지 않은시기를 아는 것이 합리적입니다.

그러나 나는 사용자가 합리적으로 강요하는 죄책감을 느낍니다.

라이브러리 노출을하는 것이 허용됩니다 weak_ptr대상에? 다른 도서관 이이 작업을 수행 했습니까?

나는이 도서관의 앱에서의 사용을 프로파일 링했으며 노출하기에는 너무 미션 크리티컬이라는 것을 알았습니다. weak_ptr 독점적으로.

일치하는 API 기능이 참조를 노출시키는 것이 더 현명할까요? 또는 약한 _ptr 또는 노출 할 수있는 물체를 만들기 위해 weak_ptr 그 자체로?

도움이 되었습니까?

해결책

만약 smart_ptrS는 이미 도서관 사용자가 직접 액세스 할 수 있으며 이미 액세스 할 수 있습니다. weak_ptrs, 단순히 해당 weak_ptr의 생성자. 그러나 만약 smart_ptrS는 모두 도서관 내부이며 다른 이야기입니다.

이 경우 각 객체가 전달되는 것이 좋습니다. weak_ptr라이브러리가 제공하는 다른 액세스 외에도 s 자체로. 사용자에게 가장 유연성을 제공합니다. 필요한 경우 weak_ptr, 그들은 즉시 접근 할 수 있습니다. 그들이 필요하다면 shared_ptr, 그들은 쉽게 얻을 수 있습니다. 그리고 그들이 객체 자체에 대한 액세스가 필요하다면, 스마트 포인터를 완전히 무시할 수 있습니다.

물론, 나는 당신의 도서관이 무엇을하는지, 어떻게 사용 또는 설계되었는지 모르겠습니다. 그것은 내 추천을 바꿀 수 있습니다.

다른 팁

도서관의 물체를 얻을 수있는 복잡한 메커니즘을 생각해 내면 사람들이 라이브러리를 사용하지 않는 것만으로도 제공됩니다. 라이브러리의 의미론이 지시하는 경우 약한 _ptrs를 사용하는 사람들이 필요하다면, 객체가 어느 시점에서 사라질 수 있다는 것을 알 수있는 방법은 없습니다. 인터페이스 표현을 가능한 한 라이브러리 사용에 대한 많은 정보를 표현하고 문서를 낮추고 사용하기가 쉽게 사용합니다.

나쁜/경험이 부족한 사용자를 중심으로 디자인 할 수 없습니다.

고객에게 액세스 권한을 부여하는 경우 weak_ptrs 그들은 단지 그것들을 잠그기 위해 잠글 수 있습니다 shared_ptr물체의 파괴를 지연시키고 결국. 라이브러리에 문제가 발생할 수 있습니다.

나는 포장하는 것이 좋습니다 weak_ptr 다른 클래스에서는 발신자에게 a shared_ptr 그것에. 그렇게하면 그들은 단지 전화 할 수 없습니다 weak_ptr<T>::lock(). 당신은 그것을 구현하는 방법에 영향을 줄 수있는 성능 제약이있는 것 같습니다. shared_ptr<InterfaceClass> 좋은 방법 일 수 있으며 weak_ptr 도서관 내부.

이렇게하면 이러한 구현 세부 정보를 라이브러리 인터페이스에서 보관하고 인터페이스를 변경하지 않고 구현 방식을 변경할 수 있습니다.

특히 약한 _ptrs를 노출시키는 데 아무런 문제가 없습니다. TR1에는 비슷한 스마트 포인터가 있습니다 (PDF).

TR1은 대부분 Visual Studio 및 GCC에 의해 구현되지만 다른 컴파일러는 없습니다. 그러나 관심있는 모든 컴파일러에서 구현되면 API를 재 작업하여 대신 해당 스마트 포인터를 노출시킬 수 있습니다.

라이브러리를 잘못 사용하려면 (삭제되었을 때 객체에 액세스하려고 시도) 고성능 API (API에 약한 _ptr 및 shared_ptr의 없음)를 사용하려면 다른 API를 고려할 수 있습니다. Debug 및 Nondebug 빌드의 경우.

단순하게 노출되는 객체의 클래스 만 있다고 가정 해 봅시다. 이 클래스 객체를 호출하십시오. 내부 개체에 액세스하기 위해 API에서 반환 한 포인터 유형은 다음과 같이 정의됩니다.

#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr 
#else
typedef Object * ObjectPtr;
#endif

여기서 외관은 당신이 쓰는 수업입니다. 대략적으로 다음과 같이 작동합니다.

class ObjectPtrFacade {
public:
    ObjectPtrFacade(Object *o) : wptr(o) { }
    // copy constructor and assignment here etc. (not written)
    Object * operator -> () const { return access(); }
    Object & operator * () const { return *access(); }
private:
    Object * access() { 
      assert(wptr.use_count() > 0);
      return (Object *)(wptr.lock());
    }
    weak_ptr<Object> wptr; 
}

이런 식으로 디버깅 빌드를 만들 때마다 사용되는 특별한 종류의 스마트 포인터가있어 사용 _count ()가 0보다 높다는 객체에 액세스하기 전에, 즉 객체가 여전히 존재한다고 주장합니다. 객체가 릴리스 된 경우 실패한 주장이 나타납니다. 이는 널 포인터 참조보다 낫습니다.

물론 일반적으로 API의 "멍청한"사용자가있는 경우 약점을 사용하면 도움이되지 않습니다. 잠금 ()을 호출 한 다음 약한 _ptr이 비어있는 shared_ptr을 반환 한 후에도 여전히 널 포인터 참조를 할 수 있기 때문입니다. ..

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top