2016-12-28 1 views
8

을 사용해야합니까? std::enable_shared_from_this 양식 this link을 방금 알았습니다.
그러나 아래 코드를 읽은 후에는 언제 사용해야할지 모르겠습니다. getptr()를 호출하기 전에 기존 shared_ptr이 없기 때문에 위의
우리는 언제 std :: enable_shared_from_this

try { 
     Good not_so_good; 
     std::shared_ptr<Good> gp1 = not_so_good.getptr(); 
    } catch(std::bad_weak_ptr& e) { 
     // undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17) 
     std::cout << e.what() << '\n';  
    } 

코드는 "너무 좋지 않다"입니다. 그래서 좋은 일이되어야합니다 :

std::shared_ptr<Good> gp1 = std::make_shared<Good>(); // having a shared_ptr at the beginning 
std::shared_ptr<Good> gp2 = gp1->getptr(); 

을 그러나, 나는 이미이 같은하지 난 단지 코드를 할 이유 shared_ptr 개체, 한 경우 : 나는 모든 std::enable_shared_from_this을 필요로하지 않는다는 것을 의미 std::shared_ptr<Good> gp2 = gp1;을. std::enable_shared_from_this를 사용하여 내 의견으로는


, 우리는 the double-delete problem를 방지 할 수 있도록 하나 이상의 shared_ptr 객체가 같은 제어 블록이 있는지 확인하는 것입니다. 그러나 내가 처음에 shared_ptr을 만들 것을 상기시켜야한다면. 왜 그냥 원시 포인터를 사용하는 대신 shared_ptr 개체를 사용하여 새로운 개체를 만들 것을 상기시키지 않습니까?

+0

'void f (좋은 & g);/* ... */f (* gp1);/* ... */void f (좋은 & g) {/ * 지금 뭐? * /}' – milleniumbug

+0

@milleniumbug 미안 해요 – Yves

+1

'f'는 공유 포인터가 아니라 참조를 취하기 때문에'shared_ptr'에 접근 할 수 없습니다. 때때로 참조를 취하기 위해 변경할 수 있지만, 그러나 회원 함수가 아니라면 - this는 항상 미가공 포인터입니다. – milleniumbug

답변

6

std::enable_shared_from_this<T>이 유용 할 때 힌트가 있습니다. 요청에 따라 개체를 생성 할 때 개체 자체에 대한 포인터를 반환해야 할 수 있습니다. 결과가 std::shared_ptr<T>이면 일반적으로 액세스 할 수없는 멤버 함수 내에서 그러한 포인터를 반환해야합니다. std::shared_ptr<T>

std::enable_shared_from_this<T>에서 파생 된 것은 T 유형의 포인터 만 주어진 std::shared_ptr<T>을 보유 할 수있는 방법을 제공합니다. 그러나 개체가 이미 std::shared_ptr<T>를 통해 관리되어 있다고 가정 않습니다 이렇게와 객체가 스택에 할당되어있는 경우는 신체 상해를 만들 것입니다 : 현실적인 시나리오에서

struct S: std::enable_shared_from_this<S> { 
    std::shared_ptr<S> get_object() { 
     return this->shared_from_this(); 
    }; 
} 

int main() { 
    std::shared_ptr<S> ptr1 = std::make_shared<S>(); 
    std::shared_ptr<S> ptr2 = ptr1->get_object(); 
    // ... 
} 

아마 어떤 조건이 이는 std::shared_ptr<T>을 아래 현재 오브젝트에 대한 값이 리턴됩니다.

2

불투명 포인터와 같은 템플릿 std::shared_ptr<T>을 사용할 수없는 유스 케이스가 있습니다. 이 경우

, 그것은이있는 것이 유용 : some_file.cpp some_other.c에서

struct A : std::enable_shared_from_this<A> {}; 

extern "C" void f_c(A*); 
extern "C" void f_cpp(A* a) { 
    std::shared_ptr<A> shared_a = a->shared_from_this(); 
    // work with operation requires shared_ptr 
} 

int main() 
{ 
    std::shared_ptr<A> a = std::make_shared<A>(); 
    f_c(a.get()); 
} 

에서

struct A; 
void f_cpp(struct A* a); 
void f_c(struct A* a) { 
    f_cpp(a); 
} 
+0

나는 혼란 스럽다. 왜 f_cpp에서 a에 sharea_ptr을 사용해야합니까? 만약 f_cpp가 그것을 필요로한다면, 그것은 원시 pointef A * 대신에 shared_ptr을 받아 들여야한다. – Gavin

2

은 이제 나는를 표현하고 싶은 말은하자 계산 트리. 표현식에 대한 두 개의 포인터를 사용하여 표현식에서 파생되는 클래스로 표현 된 표현식을 추가함으로써 표현식을 재귀 적으로 평가할 수 있습니다. 그러나 평가를 어딘가에 끝내야하므로 숫자를 평가 해 보겠습니다.

class Number; 

class Expression : public std::enable_shared_from_this<Expression> 
{ 
public: 
    virtual std::shared_ptr<Number> evaluate() = 0; 
    virtual ~Expression() {} 
}; 

class Number : public Expression 
{ 
    int x; 
public: 
    int value() const { return x; } 
    std::shared_ptr<Number> evaluate() override 
    { 
     return std::static_pointer_cast<Number>(shared_from_this()); 
    } 
    Number(int x) : x(x) {} 
}; 

class Addition : public Expression 
{ 
    std::shared_ptr<Expression> left; 
    std::shared_ptr<Expression> right; 
public: 
    std::shared_ptr<Number> evaluate() override 
    { 
     int l = left->evaluate()->value(); 
     int r = right->evaluate()->value(); 
     return std::make_shared<Number>(l + r); 
    } 
    Addition(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right) : 
     left(left), 
     right(right) 
    { 

    } 
}; 
는 이중 삭제가 발생합니다 때문에 return std::shared_ptr<Number>(this);Number::evaluate()을 구현의 "명백한"방법이 파괴되는 것을

Live on Coliru

.

+0

'evaluate'의 리턴 타입은'std :: shared_ptr '이어야하며 모든 악의적 인 캐스팅으로부터 당신을 보호합니다. –

+0

'Number'와'Addition'의 기본 클래스를 지정하는 것을 잊어 버렸습니다. – Oktalist

+0

@BenVoigt 예,이 샘플 코드에서는 간단히 설명합니다. 내 프로그램에는 다른 유형이있어서 처음에 그렇게하지 못했습니다. (슬프지만'std :: shared_from_this()'에서 캐스팅을 사용해야 만합니다.하지만 그게 인생이라고 생각합니다) – milleniumbug

관련 문제