Я пишу обертку 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));
}
};
Я могу управлять экземплярами String
с помощью std::shared_ptr
. Но когда мой объект 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?
Update
Вот версия, которая, кажется, работает (при компиляции в 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));
}
};