首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指向智能指针托管数组中的智能指针。

指向智能指针托管数组中的智能指针。
EN

Stack Overflow用户
提问于 2016-06-09 03:42:24
回答 1查看 846关注 0票数 1

我正在围绕存储在字符数组中的一个低级对象编写一个C++包装器。我希望能够使用智能指针来管理我的班级的生命周期。我的类中有几个成员需要将指针返回到对象中;因为它们不是单独的分配,所以我不能为它们使用标准的智能指针,一旦释放主对象,这些指针就会失效。

具体而言,请考虑以下简单的string类:

代码语言:javascript
复制
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));
    }
};

我可以使用String管理std::shared_ptr的实例。但是,当我的String对象被销毁时,getString()getSubstring()返回的任何指针都将无效。我希望getString()getSubstring()能够返回某种类型的智能指针,该指针将保存对父对象的引用,因此以下代码是有效的:

代码语言:javascript
复制
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呢?

更新

下面是一个基于Yakk的建议的版本(当使用gcc或clang编译为C++11时):

代码语言:javascript
复制
#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));
    }
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-09 04:04:31

您可能需要shared_ptr“别名”构造函数。

如果您有C++1z支持,甚至可以得到[]

你的“某样东西”就是shared_ptr

代码语言:javascript
复制
std::shared_ptr<char>
getSubstr(size_t idx) {
    if (idx < len)
        return {shared_from_this(), &s[idx]};
    else
        return {};
}

并将enable_shared_from_this添加到String中。

或者,直接通过shared_ptr管理String中的缓冲区。

代码语言:javascript
复制
std::shared_ptr<char> s;

代码语言:javascript
复制
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管理--您可以将它放在向量中或在堆栈上声明它。C++在这样的常规类型上蓬勃发展。

同时,内部缓冲区是智能指针管理的,因此子字符串不能悬空。

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

参考计数块具有强计数、弱计数和破坏功能。

别名构造函数允许您使用不同的共享指针的引用计数块和任意数据指针。这是为了将共享指针返回给由共享指针管理的类的成员,这基本上就是您要做的事情。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37716373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档