Необязательный указатель владения - PullRequest
0 голосов
/ 15 апреля 2020

Давайте рассмотрим этот класс, который владеет или просматривает указатель в зависимости от того, как он построен.

template<class T>
class OptionalUniquePtr
{
  public:

    OptionalUniquePtr(p*)
    : m_p(p)
    {}

    OptionalUniquePtr(std::unique_ptr<T>&& p)
    : m_owned_p(std::move(p))
    , m_p(p)
    {}

    T* get()
    {
      return m_p;
    }

 private:

   std::unique_ptr<T> m_owned_p;
   T *m_p;
};

Помимо твиков или оптимизаций, мой вопрос: это плохая идея? Я работаю над кодом, который может по желанию владеть или просматривать некоторые указатели:

std::unique_ptr<Bar> b1 = ...;
Bar *b2 = ...;
// one million lines later
Foo f1(std::move(b1),...); // ownership transfered to f1
Foo f2(b2,...); // just viewing b2, caller manages lifetime. Risky, but usually owners have long lifetime

Представьте, что Foo - это большой класс, который делает что-то на Bar среди других вещей. Я хочу, чтобы Foo был гибким, чтобы принять и то и другое, чтобы он мог иметь внутри OptionalUniquePtr Альтернативой является шаблон Foo, подобный этому

Foo<std::unique_ptr<Bar>> f1(std::move(b1),...);
Foo<Bar*> f1(b2,...);

Преимущество этого второго подхода состоит в том, чтобы быть более явным в отношении владения памятью.

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

Каково мнение сообщества о OptionalUniquePtr?

Спасибо

Simone

1 Ответ

0 голосов
/ 15 апреля 2020

Ответ заключается в том, что этот вид «необязательного владения» уже реализован std :: shared_ptr. Код выглядит так:

std::unique_ptr<Bar> bar1 = ...;
Bar* bar2 = ...;

Foo f1(std::move(bar1));
Foo f2(bar2);

, где

class Foo
{
  public:

    // Onwing ctor
    Foo(std::unique_ptr<Bar>&& b)
    : m_bar_ptr(std::move(b))
    {}

    // Viewing ctor. It uses shared_ptr aliasing ctor.
    Foo(Bar* b)
    : m_bar_ptr(nullptr, b)
    {}

  private:

    std::shared_ptr<Bar> m_bar_ptr;
  };
...