Есть ли класс интеллектуального указателя Boost, который можно настроить так, чтобы он не удалялся при уничтожении?

У меня есть список умных указателей. Я хочу, чтобы некоторые из этих интеллектуальных указателей действовали как обычные указатели, то есть они просто являются ссылкой на экземпляр и не участвуют в его освобождении. Например, они могут указывать на экземпляры, размещенные в стеке. Остальные интеллектуальные указатели в списке должны действовать как обычный boost :: shared_ptr.

Вот как может выглядеть класс:

template<class T> smart_ptr {
private:
    T *p;
    boost::shared_ptr<T> sp;
public:
    smart_ptr(T *p): p(p), shared(0) { } // p will not be deleted
    smart_ptr(boost::shared_ptr<T> &sp): p(sp.get()), sp(sp) { }
    T *get() const { return p; }
}

Если есть класс повышения, который делает это, я бы предпочел использовать его вместо того, чтобы писать класс самостоятельно. Оказывается, их нет, или я ошибаюсь?


person Community    schedule 20.07.2009    source источник
comment
Если желаемый указатель не предназначен для освобождения указателя, в чем его умная часть? Что вы хотите от него, чего нет у простого старого указателя (T *)?   -  person Tadeusz Kopec    schedule 20.07.2009
comment
OP хочет один и тот же статический тип для обоих, поэтому он может смешивать в коллекции экземпляры, владеющие и не владеющие экземплярами.   -  person Marc Mutz - mmutz    schedule 29.07.2009


Ответы (4)


Один конструктор для shared_ptr принимает метод деструктора, и вы можете передать пустой функтор.

Использование настраиваемого Deallocator в boost :: shared_ptr

(Вам нужна только пустая функция.)

person Sam Harwell    schedule 20.07.2009
comment
Но можно ли смешивать и сопоставлять shared_ptrs с разными удалителями в одном списке? Они становятся разными типами, не так ли? - person Kim Gräsman; 20.07.2009
comment
Нет, средство удаления не относится к типу shared_ptr, поэтому да, вы можете смешивать и сопоставлять разные средства удаления в одной коллекции. - person Marc Mutz - mmutz; 20.07.2009
comment
Я считаю, что стандарт TR1 исключает эту технику; удаление указателя должно быть четко определено, даже если вы укажете настраиваемую функцию деструктора. - person Daniel Earwicker; 20.07.2009
comment
@Earwicker: нет, слава богу (Earwicker удалил ответ, в котором говорилось об этом, но не комментарий). - person Steve Jessop; 20.07.2009
comment
Спасибо за этот ответ! Это помогло мне выйти из плохой ситуации, когда один устаревший модуль предоставлял только ссылку на объект, а другой принимал только shared_ptr. С помощью пустого деструктора я смог предоставить shared_ptr, который не удалял бы объект, принадлежащий первому модулю. - person Kiv; 10.01.2011

Для этого у меня есть этот маленький класс в моем наборе инструментов:

struct nodelete {
    template <typename T>
    void operator()( T * ) {}
};

Использование:

int main() {
    SomeClass sc;
    boost::shared_ptr<SomeClass> p( &sc, nodelete() );
    // ...
}
person Marc Mutz - mmutz    schedule 20.07.2009

Звучит как повышение :: weak_ptr: http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/weak_ptr.htm.

Но вы можете создать weak_ptr только из shared_ptr, поэтому я не уверен, как это сработает для ваших объектов, выделенных стеком.

person Kim Gräsman    schedule 20.07.2009

Пахнет плохим дизайном.

Я не могу придумать разумную ситуацию, когда вы бы не хотели удалять указатель. Вот (необоснованные ИМО) ситуации:

1) объекты статической длительности. Вместо этого рассмотрите возможность использования примеси синглтона (используйте CRTP для смешивания синглтона, у которого есть метод instance (), который возвращает копию локального статического shared_ptr ‹>; локальная статика небезопасна для потоков, поэтому вам также понадобится соответствующий статический мьютекс, если это может вызываться несколькими потоками). Преимущество использования правильного синглтона заключается в том, что ваш синглтон будет уничтожен при выходе после других объектов, которые продолжают удерживать shared_ptr ‹> для него.

2) объекты, созданные в стеке. Только не делай этого. Вместо этого создайте объект в куче, защищенный shared_ptr ‹>. Если вам нужно создать shared_ptr ‹> для объекта в разных частях кода (т.е. вы не можете брать копии из исходного shared_ptr‹>), тогда наследуйте от boost :: enable_shared_from_this ‹> и получите shared_ptr‹>. из shared_from_this ().

Есть ли еще одна причина, по которой вам нужен shared_ptr ‹>, который ничего не удаляет?

person James Taylor    schedule 11.03.2010