문제

나는 가로 질러 달렸다 enable_shared_from_this boost.asio 예제를 읽고 문서를 읽은 후에는 이것이 어떻게 올바르게 사용되어야하는지에 대해서도 여전히 길을 잃었습니다. 누군가 나 에게이 수업을 사용하는 시점에 대한 예제 및/또는 설명이 의미가 있습니다.

도움이 되었습니까?

해결책

유효한 것을 얻을 수 있습니다 shared_ptr 인스턴스 this, 당신이 가진 모든 것일 때 this. 그것 없이는 당신은 shared_ptr 에게 this, 당신이 이미 회원을 가지고 있지 않는 한. 이 예제에서 ENABLE_SHARED_FROM_THIS에 대한 문서를 부스트하십시오:

class Y: public enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

메소드 F ()가 유효한 것을 반환합니다 shared_ptr, 멤버 인스턴스가 없더라도. 단순히 이것을 할 수는 없습니다.

class Y: public enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_ptr<Y>(this);
    }
}

이것이 반환 된 공유 포인터는 "적절한"과 다른 참조 수를 가질 것이며, 그 중 하나는 객체를 삭제할 때 매달려있는 참조를 잃고 유지하게됩니다.

enable_shared_from_this C ++ 11 표준의 일부가되었습니다. 부스트뿐만 아니라 거기에서도 얻을 수 있습니다.

다른 팁

약한 포인터에 관한 Dobbs Dr Article 에서이 예는 이해하기 쉽다고 생각합니다 (출처 : http://drdobbs.com/cpp/184402026):

... 이와 같은 코드는 올바르게 작동하지 않습니다.

int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);

둘 중 어느 것도 shared_ptr 물체는 다른 것에 대해 알고 있으므로 둘 다 파괴 될 때 자원을 해제하려고합니다. 일반적으로 문제가 발생합니다.

마찬가지로, 멤버 함수에 필요한 경우 a shared_ptr 호출되는 객체를 소유 한 객체는 즉, 객체를 즉시 생성 할 수는 없습니다.

struct S
{
  shared_ptr<S> dangerous()
  {
     return shared_ptr<S>(this);   // don't do this!
  }
};

int main()
{
   shared_ptr<S> sp1(new S);
   shared_ptr<S> sp2 = sp1->dangerous();
   return 0;
}

이 코드는보다 미묘한 형태이지만 이전 예와 동일한 문제가 있습니다. 그것이 구성되면, shared_ptR 객체 sp1 새로 할당 된 리소스를 소유합니다. 멤버 함수 내부의 코드 S::dangerous 그것에 대해 모릅니다 shared_ptr 객체, 그래서 shared_ptr 반환하는 객체는 구별됩니다 sp1. 새로운 복사 shared_ptr 대상 sp2 도움이되지 않습니다. 언제 sp2 범위를 벗어나면 자원을 발표하고 언제 sp1 범위를 벗어나면 리소스를 다시 출시합니다.

이 문제를 피하는 방법은 클래스 템플릿을 사용하는 것입니다. enable_shared_from_this. 템플릿은 하나의 템플릿 유형 인수를 가져옵니다.이 템플릿 유형 인수는 관리되는 리소스를 정의하는 클래스의 이름입니다. 그 클래스는 차례로 템플릿에서 공개적으로 파생되어야합니다. 이와 같이:

struct S : enable_shared_from_this<S>
{
  shared_ptr<S> not_dangerous()
  {
    return shared_from_this();
  }
};

int main()
{
   shared_ptr<S> sp1(new S);
   shared_ptr<S> sp2 = sp1->not_dangerous();
   return 0;
}

이렇게하면 전화하는 물건이 shared_from_this 소유해야합니다 shared_ptr 물체. 이것은 작동하지 않습니다 :

int main()
{
   S *p = new S;
   shared_ptr<S> sp2 = p->not_dangerous();     // don't do this
}

견과류와 볼트 관점에서 내 설명은 다음과 같습니다 (상단 답변은 나와 함께 '클릭하지 않았다). *이것은 Visual Studio 2012와 함께 제공되는 shared_ptr 및 enable_shared_from_this의 소스를 조사한 결과입니다. 아마도 다른 컴파일러는 enable_shared_from_this ...*를 구현할 수 있습니다.

enable_shared_from_this<T> 개인을 추가합니다 weak_ptr<T> 인스턴스 T '하나의 진정한 참조 수'의 경우 T.

따라서 처음 a를 만들 때 shared_ptr<T> 새로운 t*에, 그 t*의 내부 약점 _ptr은 1의 refcount로 초기화됩니다. shared_ptr 기본적으로 이것으로 돌아갑니다 weak_ptr.

T 그러면 그 방법으로 전화 할 수 있습니다 shared_from_this 인스턴스를 얻으려면 shared_ptr<T> 저것 내부적으로 저장된 참조 수로 뒤로. 이런 식으로, 당신은 항상 하나의 장소가 있습니다 T*의 ref-count는 여러 가지가 아닌 저장됩니다 shared_ptr 서로에 대해 모르는 인스턴스와 각각은 shared_ptr 그것은 Ref-Counting을 담당합니다 T 그들의 ref-count가 0에 도달하면 그것을 삭제합니다.

Boost :: Instrusive_ptr을 사용하면이 문제가 발생하지 않습니다. 이것은 종종이 문제를 해결하는 더 편리한 방법입니다.

C ++ 11 이상에서 정확히 동일합니다. 반환 능력을 가능하게하는 것입니다. this 그 이후로 공유 포인터로 this 당신에게 생 포인터를 제공합니다.

다시 말해, 이와 같이 코드를 전환 할 수 있습니다.

class Node {
public:
    Node* getParent const() {
        if (m_parent) {
            return m_parent;
        } else {
            return this;
        }
    }

private:

    Node * m_parent = nullptr;
};           

이것으로 :

class Node : std::enable_shared_from_this<Node> {
public:
    std::shared_ptr<Node> getParent const() {
        std::shared_ptr<Node> parent = m_parent.lock();
        if (parent) {
            return parent;
        } else {
            return shared_from_this();
        }
    }

private:

    std::weak_ptr<Node> m_parent;
};           

또 다른 방법은 a를 추가하는 것입니다 weak_ptr<Y> m_stub 회원 class Y. 그런 다음 작성하십시오.

shared_ptr<Y> Y::f()
{
    return m_stub.lock();
}

당신이 얻는 수업을 변경할 수 없을 때 유용합니다 (예 : 다른 사람들의 도서관 확장). 회원을 초기화하는 것을 잊지 마십시오. m_stub = shared_ptr<Y>(this), 생성자 중에도 유효합니다.

상속 계층 구조 에이 스터브가 더 많으면 대상의 파괴를 방해하지 않습니다.

편집하다: 사용자 NoBar가 올바르게 지적했듯이, 할당이 완료되고 임시 변수가 파괴 될 때 코드는 y 객체를 파괴합니다. 따라서 내 대답이 잘못되었습니다.

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