2016-06-09 216 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()返回的任何指針都將無效。我會喜歡有用於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()); 

有什麼辦法來實現這使用標準的C++功能?如果不是,Boost呢?

更新

這裏,似乎工作時(如C++ 11使用gcc或鐺編譯),基於Yakk的建議版本:

#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++ 1z支持,你甚至會得到[]

你的「SOMETHING」只是shared_ptr

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

並將enable_shared_from_this加到String。你 -

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++在像這樣的常規類型上蓬勃發展。

與此同時內部緩衝區是智能指針管理的,所以子串不能懸垂。

這是別名的構造函數。共享指針有兩個組件:一個引用計數塊和一個數據指針。

引用計數塊具有強計數,弱計數和破壞函數。

使用別名構造函數可以使用不同的共享指針的引用計數塊和任意數據指針。這是爲了將共享指針返回給由共享指針管理的類的成員,這基本上就是你在做什麼。