2017-09-12 1 views
-1

(으)로 구성되었습니다. std::map에 클래스의 모든 개체를 추가하고 싶습니다. 내가 객체를 복사하지 않기 때문에,이 같은 스마트 포인터를 사용하여 해결 방법을 얻으려고 :std :: shared_ptr이 (가)

Class.h을

class A : public std::enable_shared_from_this<A> { 
public: 
    A(); 
    ~A(); 
    static std::map<uint32_t, std::shared_ptr<A>> getObjects(); 
private: 
    static uint32_t counter; 
    uint32_t id; 
    static std::map<uint32_t, std::shared_ptr<A>> objects; 
}; 

Class.cpp

A::A() 
{ 
    id = counter++; 
    std::shared_ptr<A> ptr = std::make_shared<A>(); 
    objects[id] = ptr->shared_from_this(); 
} 

A::~A() 
{ 
    objects.erase(id); 
} 

std::map<uint32_t, std::shared_ptr<A>> A::getObjects() 
{ 
    return objects; 
} 

uint32_t A::counter=0; 

std::map<uint32_t, std::shared_ptr<A>> A::objects; 

이것은 잘 컴파일되지만 이것을 사용하려고 할 때

int main(){ 
    A a; 
    A b; 
    auto objects = A::getObjects(); 
} 

내가 얻을 분할 오류

: 11`

내가

A::A() 
{ 
    id = counter++; 
    std::shared_ptr<A> ptr(this); 
    objects[id] = ptr->shared_from_this(); 
} 

에 생성자를 변경하려고하면 포인터가 해제되고

할당되지 않은 내가 얻을

기본적으로 std::shared_ptr<A>this에서 생성해야하지만 작동시키지 못합니다.

+1

[this] (http://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this)을 위반하는 것 같습니다 : * 이전에 공유 된 객체에만'shared_from_this'를 호출 할 수 있습니다 즉,'std :: shared_ptr'에 의해 관리되는 객체에 대해서. * – chris

+0

이것을 원한다면'A' 형의 객체 만 shared_ptr로 할당해야합니다 – Justin

답변

1

원래 코드는 스택 오버 플로우가 있습니다.당신이 다음도 시도 무엇

작동하지 않습니다 :이 객체의 수명이 std::shared_ptr에 의해 관리되는 경우

A::A() 
{ 
    id = counter++; 
    std::shared_ptr<A> ptr(this); 
    objects[id] = ptr->shared_from_this(); 
} 

shared_from_this() 만 작동합니다.


할 수있는 작업에는 몇 가지 옵션이 있습니다. 정적 팩터 리 함수를 사용하고 생성자를 드러 낼 수는 없지만 클래스에 예상치 못한 디자인입니다.

내가보기에 더 선명한 디자인은 핌플 패턴과 비슷한 것을하는 것입니다. A의 실제 구현에 std::shared_ptr을 입력하고 shared_ptr이 포함 된 개체의 기능을 래핑 할 수 있습니다.

1

공유 포인터가 관리하지 않는 개체에 대한 소유 공유 포인터를 가져올 수 없습니다.

수명주기가 자동 저장 객체의 수명이 공유 포인터에 의해 관리되지 않을 수 있습니다.

일반적으로 개체 및 개체 수명은 개체 자체가 아니라 개체를 만드는 코드에 의해 제어되므로 디자인을 수행 할 수 없습니다.

스마트 pImpl 래퍼는 개체의 내장에 수명이 결정된 별도의 스마트 포인터를 만들 수 있습니다. 그러나 공유 된 포인터 솔루션은지도를 파괴하면 마지막 공유 포인터를 죽일 수 있기 때문에 불법입니다.지도 코드를 다시 입력하고 지우려고 시도합니다. 이것은 정의되지 않은 동작입니다.

약한 포인터 맵 내용, pImpl 기반 래퍼, 인스턴스 등록을 취소하는 스마트 삭제자 및 기타 작업이 작동 할 수 있습니다. 그것은 SO 대답의 범위를 벗어납니다.

개체 수명, 취약한 ptrs 작동 방식, 대체 deleter, pImpl 기반 값 유형 및 수많은 다른 주제를 관리하는 방법에 대해 알아야합니다. 행운을 빕니다.

A::A() 
{ 
    id = counter++; 
    std::shared_ptr<A> ptr = std::make_shared<A>(); 
    objects[id] = ptr->shared_from_this(); 
} 

당신은 무조건 A의 생성자 내에서 A를 구성 :

1

글로벌지도에 저장된 클래스의 모든 인스턴스가 필요한 경우 다음을 시도해 볼 수 있습니다. 1) 모든 생성자 숨기기. 2) static ('factory') 메소드를 통해서만 새로운 객체를 생성합니다. 귀하의 경우이 메서드는 shared_ptr을 반환 할 수 있습니다 (또는 참조를 반환 할 수 있다고 가정하면 shared_ptr 자체가 전역 맵에 비공개이며,이 경우 unique_ptr을 사용할 수도 있습니다).

관련 문제