2011-03-23 3 views
7

이 주제와 관련하여 이미 몇 가지 질문이 있지만 무엇을해야할지 모르겠습니다. 코드베이스는 shared_ptr을 여러 곳에서 사용합니다. 나는 그것을 쓸 때 소유권을 명확하게 정의하지 않았다는 것을 인정해야한다.메소드에 전달할 때 shared_ptr을 weak_ptr로 변환해야합니까?

우리는 나는 우리의 디자인에서 실수를 수정하고 싶은 첫 번째 (간접) 순환 종속성을 발견 한 후

void doSomething(shared_ptr<MyClass> ptr) 
{ 
     //doSomething() is a member function of a class, but usually won't store the ptr 
     ptr->foo(); 
     ... 
} 

같은 몇 가지 방법이있다. 그러나 나는 정확히 어떻게 확신 할 수 없다. 위의 방법을 변경하면 어떤 이점이 있습니까

void doSomething(weak_ptr<MyClass> ptr) 
{ 
     shared_ptr<MyClass> ptrShared = ptr.lock(); 
     ptrShared->foo(); 
     ... 
} 

?

Google 스타일 가이드를 포함하여 처음에는 소유권을 올바르게 유지하는 것이 중요하다고 말하기 때문에 혼란 스럽습니다 (위의 방법을 사용한 예에서와 같이 많은 사람들이 아마도 weak_ptrs의 도입을 의미 할 수도 있지만 또한 우리가 가지고있는 많은 멤버 변수들에 대해서). 순환 종속성을 깨기 위해 weak_ptr을 사용해야한다고 말하는 사람들도 있습니다 (아래 링크 참조). 그러나 그것들을 감지하는 것이 항상 쉬운 일은 아니기 때문에 문제가 발생하여 (그리고 깨닫게 될 때까지) shared_ptr을 사용해야하는지 궁금하다.

의견을 보내 주셔서 감사합니다.

우리는 명확하게 소유권을 정의하지 않았다 또한

+0

shared_ptr & 더 좋을까요? – DanDan

+1

"그들을 탐지하는 것이 항상 쉬운 것은 아닙니다"- 그렇다면 실제로 설계 프로세스에 더 많은 단계를 추가해야합니다. 클래스 관계 다이어그램의 밝은 선과 어두운 선. 또한 모든 "비 소유자"가되기 전에 "소유자"가 파괴되지 않는 대부분의 비대칭 관계에 대해 약한 포인터가 아닌 원시 포인터로 브레이크주기를 고려할 수 있습니다. –

+1

@ DanDan : 나는 그렇게 생각하지 않는다. http://stackoverflow.com/questions/327573/c-passing-references-to-boostshared-ptr – Philipp

답변

6

참조하십시오.

누가 소유하고 있는지 명확하게 정의해야합니다. 이 문제를 해결할 다른 방법은 없습니다. 임의로 shared_ptr의 사용을 weak_ptr으로 바꿔도 더 나은 결과를 내지는 못합니다.

+0

오케이, 디자인이 (아직 :-)) 너무 나쁘지는 않다고 생각합니다. 너무 나쁨. 그러나 문제는 남아 있습니다 : 내가 원을 발견하면 어디서든 weak_ptrs를 도입해야합니까? (더 이상있을 경우) 또는 객체/메소드가 소유권을 갖고 있지 않은 곳 어디에서나 사용할 수 있습니까? – Philipp

+1

@Phillip - 예제를 보면, weak_ptr과 shared_ptr을 넘기는 사이에 아무런 차이가 없다. weak_ptr을 사용하려면 먼저 shared_ptr을 작성해야합니다.이 방법은 처음에 shared_ptr을 전달한 것과 사실상 동일합니다. – Nathanael

2

일부 사람들이 옳습니다. 프로젝트의 개체 소유권에 대한 명확한 그림이 있어야합니다.

shared_ptrs는 공유, 즉 "owned by community"입니다. 그것은 바람직하지 않을 수도 있습니다. 따라서 소유권 모델을 정의한 다음 shared_ptr 의미를 남용하지 말고 소유권을 "공유"하지 않을 때마다 일반 포인터를 사용하는 것이 좋습니다.

weak_ptrs를 사용하면 문제를 해결하는 대신 추가로 마스크 처리합니다.

4

위의 디자인을 shared_ptr에서 weak_ptr로 변경해도 이점이 없습니다. 소유권을 얻는 것은 weak_ptrs를 사용하는 것이 아니라 중요한 시간 동안 누가 shared_ptr를 저장 하는지를 관리하는 것입니다. shared_ptr을 메서드에 전달하면 해당 메서드의 일부로 내 object의 필드에 해당 shared_ptr을 저장하지 않는다고 가정 할 때 해당 데이터를 소유 한 사람을 변경하지 않았습니다.

제 경험상 weak_ptr을 사용하는 유일한 이유는 절대적으로 포인터가 있어야하고 그 사이클을 깨야 할 때입니다. 하지만 먼저 사이클을 없애기 위해 디자인을 수정할 수 있는지 고려해야합니다.

나는 일반적으로 shared_ptr와 raw 포인터를 혼합하는 것을 권장하지 않습니다. 필연적으로 원시 포인터가 그 타입의 shared_ptr을 취하는 함수에 전달되어야 할 필요가있다. weak_ptr은 운이 좋지 않은 원시 포인터를 사용하여 안전하게 shared_ptr로 변환 될 수 있습니다. 더 나쁜 것은 shared_ptr에 익숙하지 않은 개발자가 원시 포인터에서 새로운 shared_ptr을 생성하여 함수에 넘겨 주므로 함수가 반환 될 때 해당 포인터가 삭제되도록합니다. (사실이 프로덕션 코드에서이 버그를 수정해야했기 때문에 발생합니다.)

+0

"_ 필연적으로 일어난다. (...)"이 설명은 내가 SO (또는 다른 곳)에서 본 'weak_ptr'에 대한 아주 소수의 정당화 된 설명 중 하나이다. 고맙습니다. – curiousguy

3

디자인 문제가있는 것 같습니다. shared_ptr은 특정 디자인 솔루션을 구현하는 데 사용하기 쉬운 을 제공하지만 디자인을 대체 할 수있는 것은 없습니다. 까지 각 유형의 객체의 실제 수명을 확인해야만 shared_ptr을 사용하면 안됩니다. 을 실행하면 shared_ptr/weak_ptr 문제의 대부분이 사라집니다. 만약

가 그 일을, 일부 개체의 수명이 다른 개체의에 의존 않는 것으로 결정하고,이 종속성에 사이클이있는 한, 당신은 (다시, 디자인 수준) 결정해야하는 방법 그러한 사이클을 관리하려면 --- 예를 들어, shared_ptr이 올바른 솔루션이 아니거나 관련된 포인터 중 많은 수가 탐색 용이며 원시 포인터 여야합니다.

어쨌든 질문에 대한 답변은 수준의 디자인에 있습니다. 코딩 할 때 질문해야 할 경우 으로 돌아 가야합니다.

관련 문제