Какой интерфейс лучше для сохранения необработанного указателя (предоставленного пользователем) в shared_ptr - PullRequest
0 голосов
/ 06 марта 2012

В шаблоне разработки стратегии мне нужно сохранить ссылку на Композитор в Композиции (pp315 GOF ). Для одного из методов реализации клиент передаст ссылку на Compositor в конструктор Composition, я хотел бы знать, какой интерфейс API лучше с точки зрения дизайна.

Например:

1> A(boost::shared_ptr<int> ptr) // предположим, что ptr ссылается на Композитор

2> B(int* ptr) // предположим, что ptr ссылается на Композитор

Я привел следующий пример, чтобы проиллюстрировать использование двух разных интерфейсов. Они НЕ являются реализацией шаблона проектирования стратегии! Код предоставлен, чтобы помочь мне продемонстрировать различные способы, которыми клиент может вызывать Composition с помощью параметра передачи ссылки на Compositor.

#include <boost/shared_ptr.hpp>
using namespace std; // for convenience
class A {
private:    
    boost::shared_ptr<int> m_sPtr;
public:
    A(boost::shared_ptr<int> ptr) : m_sPtr(ptr) {}
    //...
};

class B {
private:    
    boost::shared_ptr<int> m_sPtr;
public:
    B(int* ptr) : m_sPtr(ptr) {}
    //...
};

int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
    boost::shared_ptr<int> temPtr(new int(100));
    A a(temPtr);

    B b(new int(200));

    return 0;
}

Спасибо

Ответы [ 3 ]

2 голосов
/ 06 марта 2012

В большинстве случаев место, где создается ресурс, отвечает за его освобождение, поэтому в целом не следует брать необработанный указатель, если ваш класс не является умным указателем.

И скоро, с помощью шаблонов с переменным числом символов в C ++ 11, вы сможете использовать make_shared (), что означает, что вы вообще не вызываете new.

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

1 голос
/ 06 марта 2012

Если вы собираетесь сохранить указатель в shared_ptr, то у вас есть , чтобы принять его как shared_ptr, а не необработанный указатель (если вы не пишете умный указатель) ваш собственный класс, который использует shared_ptr внизу. Но вы не).

Причина в том, что пользователь может уже иметь свой ресурс в shared_ptr, например, если он умело разместил его там, как только он был создан. Если вы создадите еще один shared_ptr для того же ресурса, то есть две вещи, которые в конечном итоге удалят его, и это ошибка.

Потенциально вы могли бы обойти это, используя enable_shared_from_this с вашим классом Compositor, но если нет веской причины, по которой вы не можете взять shared_ptr во-первых, нет никакого смысла.

0 голосов
/ 07 марта 2012

Лучше всего всегда (за очень редким исключением в особых случаях) сохранять указатель, выделенный с new, сразу в виде интеллектуального указателя.Поэтому процедура, используемая в A, является наилучшей.Этот интерфейс явно предписывает, чтобы указатель, переданный в качестве аргумента , хранился в интеллектуальном указателе .Ваш класс B не гарантирует этого вообще.На самом деле, даже если вы не будете осторожны в коде вызова и записи вызова A(new int(100));, вы можете быть уверены, что указатель не будет случайно пропущен, потому что (временный) shared_ptr будет создан из вашего необработанного указателя и затем передан конструктору A,Интерфейс, используемый в A, объявляет: «О вашем указателе позаботятся!»в то время как интерфейс в B говорит: «Хм ... я не знаю, что с ним будет!»

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