2016-06-09 5 views
1

문자 배열에 저장된 하위 수준 개체 주위에 C++ 래퍼를 작성하고 있습니다. 스마트 포인터를 사용하여 수업의 평생을 관리하고 싶습니다. 내 클래스의 여러 멤버는 포인터를 객체로 반환해야합니다. 이것들은 별도의 할당이 아니기 때문에 표준 스마트 포인터를 사용할 수 없으며 주 개체가 해제되면이 포인터는 유효하지 않게됩니다.스마트 포인터 관리 배열 내 스마트 포인터

은 구체성를 들어, 다음과 같은 간단한 문자열 클래스를 생각해

class 
String 
{ 
    char* s; 
    size_t len; 

protected: 
    String(const char* str) { 
     len = std::strlen(str); 
     s = new char[len]; 
     std::strcpy(s, str); 
    } 
public: 
    ~String() { 
     delete s; 
    } 

    char* 
    getString() { 
     return s; 
    } 

    char* 
    getSubstr(size_t idx) { 
     if (idx < len) 
      return &s[idx]; 
     else 
      return nullptr; 
    } 

    static std::shared_ptr<String> 
    makeString(const char* str) { 
     return std::shared_ptr<String>(new String(str)); 
    } 
}; 

나는 std::shared_ptr를 사용 String의 인스턴스를 관리 할 수 ​​있습니다. 그러나 내 String 개체가 파괴되면 getString() 또는 getSubstring()에 의해 반환 된 포인터는 유효하지 않습니다.

std::shared_ptr<String> str = String::makeString("Hello world"); 
SOMETHING<char> substr = str->getSubstr(6); 

std::printf("String: %s\n", str->getString()); 
str.reset(); 
std::printf("Substring: %s\n", substr.get()); 

달성하기 위해 어떤 방법이 있나요 : 나는 다음과 같은 코드가 유효하므로 부모 개체에 대한 참조를 개최한다 스마트 포인터의 일종을 반환 getString()getSubstring() 수있는 방법을 가지고 같은 것 이 표준 C++ 기능을 사용합니까? 그렇지 않다면 Boost는 어떻습니까? "

#include <cstring> 
#include <boost/enable_shared_from_this.hpp> 
#include <boost/shared_ptr.hpp> 

using boost::shared_ptr; 
using boost::enable_shared_from_this; 

class 
String : public enable_shared_from_this<String> 
{ 
    size_t len; 
    char* s; 

protected: 
    String(const char* str) : len(std::strlen(str)), s(new char[len]) { 
     std::copy(str, str+len, s); 
    } 
public: 
    ~String() { 
     delete s; 
    } 

    shared_ptr<char[]> 
    getString() { 
     return shared_ptr<char[]>(shared_from_this(), s); 
    } 

    shared_ptr<char[]> 
    getSubstr(size_t idx) { 
     if (idx < len) 
      return shared_ptr<char[]>(shared_from_this(), s+idx); 
     else 
      return shared_ptr<char[]>(); 
    } 

    static shared_ptr<String> 
    makeString(const char* str) { 
     return shared_ptr<String>(new String(str)); 
    } 
}; 

답변

4

당신은 아마 shared_ptr 원하는 : 여기에 업데이트

는 (C++ (11)는 GCC 또는 연타를 사용하여 컴파일 할 때) Yakk의 제안에 따라 작동하는 것 같다 버전입니다 에일리어싱 "생성자.

C++ 1z를 지원하면 []이됩니다.

귀하의 "SOME"은 단지 shared_ptr입니다.

std::shared_ptr<char> 
getSubstr(size_t idx) { 
    if (idx < len) 
     return {shared_from_this(), &s[idx]}; 
    else 
     return {}; 
} 

Stringenable_shared_from_this을 추가합니다. 당신 -

std::shared_ptr<char> s; 

String(const char* str) { 
    len = std::strlen(str); 
    s = std::shared_ptr<char>(new char[len], std::default_deleter<char[]>{}); 
    std::strcpy(s.get(), str); 
} 

std::shared_ptr<char> 
getSubstr(size_t idx) { 
    if (idx < len) 
     return {s, s.get()+idx}; 
    else 
     return {}; 
} 

이 전략의 장점은 String 공유 PTR에 의해 관리 될 필요가 있다는 것입니다 :

또는, shared_ptrString 내 통해 직접 버퍼를 관리 벡터에 고정하거나 스택에 선언 할 수 있습니다. C++은 그런 정규 타입에서 번성합니다.

내부 버퍼는 스마트 포인터로 관리되므로 하위 문자열은 매달리지 않습니다.

핵심 요소는 별칭 생성자입니다. 공유 포인터에는 참조 계산 블록과 데이터 포인터의 두 가지 구성 요소가 있습니다.

참조 카운팅 블록은 강력한 카운트, 약한 카운트 및 소거 기능을 가지고 있습니다.

별칭 생성자를 사용하면 다른 공유 포인터의 참조 계산 블록과 임의 데이터 포인터를 사용할 수 있습니다.이것은 공유 포인터에 의해 관리되는 클래스의 멤버에게 공유 포인터를 반환하기위한 것이며 기본적으로 사용자가 수행하는 작업입니다.