2016-06-09 152 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++在像这样的常规类型上蓬勃发展。

与此同时内部缓冲区是智能指针管理的,所以子串不能悬垂。

这是别名的构造函数。共享指针有两个组件:一个引用计数块和一个数据指针。

引用计数块具有强计数,弱计数和破坏函数。

使用别名构造函数可以使用不同的共享指针的引用计数块和任意数据指针。这是为了将共享指针返回给由共享指针管理的类的成员,这基本上就是你在做什么。