Я обдумывал использование unique_ptr
против shared_ptr
против own_solution
, Я обесценил последний, поскольку я почти наверняка пойму это неправильно, но у меня есть проблема с обоими unique_ptr
а также shared_ptr
в этом ни то, ни другое точно не отражает Я хочу создать менеджер ресурсов, который явно владеет ресурсом, однако я бы хотел, чтобы менеджер ресурсов также раздавал ссылки на ресурс.
Если я использую unique_ptr
в менеджере ресурсов и раздаче сырых указателей есть вероятность, что они могут уйти куда-то еще (хотя это будет против класса «контракт», я полагаю). Если я использую shared_ptr
и раздайте weak_ptr
ничто не мешает звонящему преобразовать weak_ptr
к shared_ptr
и сохранение этого, тем самым потенциально создавая цикл или, что еще хуже, ресурс, доживающий до срока службы менеджера ресурсов. Итак, я полагаю, что я ищу weak_ptr
которые не могут быть преобразованы в shared_ptr
,
Или я просто пытаюсь обеспечить соблюдение контракта с помощью некоторых строго сформулированных комментариев в коде?
Спасибо за любые мысли, которые вы можете иметь по этому поводу.
Умные указатели, такие как shared_ptr
а также unique_ptr
хорошие инструменты, когда у вас есть владеющим указатели.
Но для не владеющих указателями, т.е. указатели наблюдения, использовать необработанный указатель — это нормально.
В вашем дизайне, я думаю, что менеджер ресурсов является единственным «владельцем» ресурсов, поэтому вы можете просто иметь некоторую форму умного указателя внутри менеджер ресурсов. Например, менеджер ресурсов может иметь std::vector<std::unique_ptr<Resource>>
в качестве члена данных, или даже проще std::vector<Resource>
если твой Resource
класс предназначен для правильного хранения в std::vector
,
Затем менеджер ресурсов может выдавать извне просто не имеющие указателей наблюдения, и необработанные указатели (или ссылки C ++) подходят для этого случая.
Конечно, важно, чтобы время жизни менеджера ресурсов превышало время жизни «клиентов ресурсов».
В конце концов, вы не можете заставить никого слушать. Спросите у Microsoft, Apple или у любого разработчика библиотеки с открытым исходным кодом, они все знают эту песню. Комментарий в правильных словах и местах — ваш лучший выбор.
Избегайте создания собственного класса интеллектуальных указателей, он мешает компоновке и снижает удобочитаемость. В крайнем случае, попробуйте взглянуть на boost или любой фреймворк, с которым ваш код уже должен работать.
Если у вас есть не владельцы, они могут быть выбраны для weak_ptr
s или (если это гарантированно останется в силе в течение продолжительности) необработанные указатели.
Если вы используете shared_ptr
с внутренней (почему вы должны), лучше всего обеспечить weak_ptr
и сырые указатели.
Все эти умные указатели явно обозначают политику владения. Необработанные указатели обозначают ничего или не владеют.
auto_ptr
Не использовать, не рекомендуется использовать слишком много ловушек даже для осторожных.unique_ptr
: Единоличное владение.shared_ptr
: Совместная собственностьweak_ptr
: Нет собственности, может быть удален за вашей спиной.Итак, я полагаю, что я ищу
не может быть преобразован в shared_ptr.
Вы могли бы раздать свой маленький вспомогательный класс:
template<typename T>
class NonConvertibleWeakPtr
{
public:
NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
... // other constructors / assignment operators
bool expired() const { return p_.expired(); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
private:
T* get() const { return p_.lock().get(); }
private:
std::weak_ptr<T> p_;
};
Это немного лучше, чем необработанный указатель, потому что вы можете проверить, если ваш указатель все еще действителен.
Пример использования:
std::shared_ptr<int> sp = std::make_shared<int>(5);
{
NonConvertibleWeakPtr<int> wp(sp);
if(!wp.expired()) {
std::cout << *wp << std::endl;
}
}
Однако пользователь все еще может использовать его, например, с std::shared_ptr<T> blah(&(*wp));
, но это требует немного больше криминальной энергии.