2009-05-18 4 views
13

Мне нужен объект shared_ptr, но он автоматически создает реальный объект, когда я пытаюсь получить доступ к его членам.Есть ли C++ ленивый указатель?

К примеру, у меня есть:

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. 

Есть ли реализация, или я должен написать мой собственный?

ответ

17

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

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

будет иметь смысл содержать ребенка как auto_ptr –

+0

Но как бы вы инициализировали поля [49] -> width, чтобы иметь нетривиальное инициализированное значение (т. Е. Не 0)? Вероятно, вы захотите иметь интерфейс, который позволяет конструктору для * (поля [49]) получать свой индекс в качестве аргумента, чтобы он мог отличить себя от других полей. Это означает использование чего-то другого, кроме std: vector, и помещает вас в область разреженных векторов/матриц. –

+2

Вы можете даже использовать boost :: optional вместо указателя на ребенка. Использование boost :: optional означает, что вы используете его распределение стека. Не используется куча, тогда –

2

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

Вы уверены, что sparse matrix не тот, что вы действительно ищете?

+1

Почему вы указали на разреженную матрицу? –

+0

Поскольку разреженная матрица заполняет аналогичную (хотя и не идентичную) необходимость. Обратите внимание, что пример плаката показывает вектор «ленивых указателей»; это очень похоже на разреженную матрицу. –

0

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

10

Использование 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().

+2

'vector > v (100)' будет использовать 100 * sizeof (Box), что, возможно, хорошо, но, возможно, OP не хочет использовать память для ящиков, которые не выделены. Поскольку ОП не описал больше требований, мы не знаем ... – ephemient

+0

Вы правы, это хорошая точка :) –

+0

Правильно, я не хочу тратить пространство на не выделенные объекты. –

Смежные вопросы