Есть ли С++ ленивый указатель?
Мне нужен объект shared_ptr
, но который автоматически создает реальный объект, когда я пытаюсь получить доступ к его членам.
Например, у меня есть:
class Box
{
public:
unsigned int width;
unsigned int height;
Box(): width(50), height(100){}
};
std::vector< lazy<Box> > boxes;
boxes.resize(100);
// at this point boxes contain no any real Box object.
// But when I try to access box number 50, for example,
// it will be created.
std::cout << boxes[49].width;
// now vector contains one real box and 99 lazy boxes.
Есть ли какая-то реализация, или я должен написать свой собственный?
Ответы
Ответ 1
Это очень мало усилий, чтобы катиться самостоятельно.
template<typename T>
class lazy {
public:
lazy() : child(0) {}
~lazy() { delete child; }
T &operator*() {
if (!child) child = new T;
return *child;
}
// might dereference NULL pointer if unset...
// but if this is const, what else can be done?
const T &operator*() const { return *child; }
T *operator->() { return &**this; }
const T *operator->() const { return &**this; }
private:
T *child;
};
// ...
cout << boxes[49]->width;
Ответ 2
Используя boost::optional
, вы можете иметь такую вещь:
// 100 lazy BigStuffs
std::vector< boost::optional<BigStuff> > v(100);
v[49] = some_big_stuff;
Построит 100 ленив и присвойте один реальный some_big_stuff
в v[49]
. boost::optional
не будет использовать кучную память, но использовать размещение - новое для создания объектов в буфере, выделенном стеком. Я бы создал обертку вокруг boost::optional
следующим образом:
template<typename T>
struct LazyPtr {
T& operator*() { if(!opt) opt = T(); return *opt; }
T const& operator*() const { return *opt; }
T* operator->() { if(!opt) opt = T(); return &*opt; }
T const* operator->() const { return &*opt; }
private:
boost::optional<T> opt;
};
Теперь используется boost::optional
для работы. Он должен поддерживать конструкцию на месте, подобную этой (пример на op*
):
T& operator*() { if(!opt) opt = boost::in_place(); return *opt; }
Для чего не требуется копирование. Однако в текущем руководстве boost-manual не включена перегрузка оператора присваивания. Источник, однако. Я не уверен, является ли это всего лишь дефектом в руководстве, или намеренно ли его документация упущена. Поэтому я бы использовал более безопасный способ, используя назначение копии, используя T()
.
Ответ 3
Я никогда не слышал об этом, но опять же есть много вещей, о которых я никогда не слышал. Как "ленивый указатель" помещал полезные данные в экземпляры базового класса?
Вы уверены, что разреженная матрица - это не то, что вы действительно ищете?
Ответ 4
Насколько я знаю, такой реализации не существует. Было бы нелегко создать его, хотя.