Есть ли C ++ ленивый указатель? - PullRequest
14 голосов
/ 18 мая 2009

Мне нужен объект типа 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.

Есть ли какая-то реализация, или я должен написать свою собственную?

Ответы [ 4 ]

18 голосов
/ 18 мая 2009

Это очень мало усилий, чтобы бросить свой собственный.

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;
10 голосов
/ 18 мая 2009

Используя 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; }

Что не требует копирования. Однако текущее усиление не включает перегрузку оператора присваивания. Источник делает, однако. Я не уверен, является ли это просто дефектом руководства или его преднамеренно пропущена документация. Поэтому я бы использовал более безопасный способ, используя назначение копирования, используя T().

2 голосов
/ 18 мая 2009

Я никогда не слышал о таких вещах, но опять же есть много вещей, о которых я никогда не слышал. Как бы «ленивый указатель» поместил полезные данные в экземпляры базового класса?

Вы уверены, что разреженная матрица - это не то, что вы действительно ищете?

0 голосов
/ 18 мая 2009

Насколько я знаю, такой реализации не существует. Было бы не сложно создать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...