shared ptr — C ++ shared_ptr против unique_ptr для управления ресурсами

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

Если я использую unique_ptr в менеджере ресурсов и раздаче сырых указателей есть вероятность, что они могут уйти куда-то еще (хотя это будет против класса «контракт», я полагаю). Если я использую shared_ptr и раздайте weak_ptrничто не мешает звонящему преобразовать weak_ptr к shared_ptr и сохранение этого, тем самым потенциально создавая цикл или, что еще хуже, ресурс, доживающий до срока службы менеджера ресурсов. Итак, я полагаю, что я ищу weak_ptr которые не могут быть преобразованы в shared_ptr,

Или я просто пытаюсь обеспечить соблюдение контракта с помощью некоторых строго сформулированных комментариев в коде?

Спасибо за любые мысли, которые вы можете иметь по этому поводу.

6

Решение

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

В вашем дизайне, я думаю, что менеджер ресурсов является единственным «владельцем» ресурсов, поэтому вы можете просто иметь некоторую форму умного указателя внутри менеджер ресурсов. Например, менеджер ресурсов может иметь std::vector<std::unique_ptr<Resource>> в качестве члена данных, или даже проще std::vector<Resource> если твой Resource класс предназначен для правильного хранения в std::vector,

Затем менеджер ресурсов может выдавать извне просто не имеющие указателей наблюдения, и необработанные указатели (или ссылки C ++) подходят для этого случая.

Конечно, важно, чтобы время жизни менеджера ресурсов превышало время жизни «клиентов ресурсов».

6

Другие решения

В конце концов, вы не можете заставить никого слушать. Спросите у Microsoft, Apple или у любого разработчика библиотеки с открытым исходным кодом, они все знают эту песню. Комментарий в правильных словах и местах — ваш лучший выбор.

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

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

Все эти умные указатели явно обозначают политику владения. Необработанные указатели обозначают ничего или не владеют.

  • auto_ptrНе использовать, не рекомендуется использовать слишком много ловушек даже для осторожных.
  • unique_ptr: Единоличное владение.
  • shared_ptr: Совместная собственность
  • weak_ptr: Нет собственности, может быть удален за вашей спиной.
  • необработанный указатель
    • Явное отсутствие собственности с гарантированным увеличением срока службы
    • или ручное управление собственностью.
10

Итак, я полагаю, что я ищу
не может быть преобразован в 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));, но это требует немного больше криминальной энергии.

4
По вопросам рекламы [email protected]