Вопрос

Я обдумывал использование 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_ptrs или (если гарантированно, что они останутся действительными в течение всего времени) необработанные указатели.
Если вы используете shared_ptrвнутри компании (почему вам это нужно), лучше всего предоставить weak_ptr и необработанные указатели.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top