Как вернуть умный указатель на переменную-член?

Я пытаюсь создать accessor для переменной члена класса с помощью интеллектуальных указателей. Здесь код:

class MyResource
{
};

class MyClass
{
public:
    std::unique_ptr<MyResource> getResource();
private:
    std::unique_ptr<MyResource> resource;
};

std::unique_ptr<MyResource> MyClass::getResource()
{
    return this->resource;
}

Ошибка, которую я пытаюсь скомпилировать:

не может получить доступ к частному члену, объявленному в классе 'std :: unique_ptr <_Ty>'

Добавление .get в this->resource конечно, не работает, потому что тип возвращаемого значения изменяется.

Должен ли я использовать unique_ptr здесь? Это просто проблема синтаксиса? Неужели я полностью ошибаюсь?

мой фон с умными указателями: я использую простые указатели уже пару лет отчасти потому, что не могу найти подробное объяснение того, когда использовать какие типы интеллектуальных указателей и как их использовать. Я устал от оправданий, поэтому я просто погружаюсь. Думаю, я понимаю, что такое умные указатели и почему их использовать, но я очень мало разбираюсь в деталях. На данный момент я полностью потерял в к бесконечному Q & A о смарт - указатели.

Ответ 1

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

Уникальный указатель говорит: "Я являюсь единственным владельцем плацдарма. Я уничтожу его, когда выйду из сферы действия".

Общий указатель говорит: "Я одна из группы друзей, которые разделяют ответственность за плацдарм. Последний из нас, чтобы выйти из сферы действия, уничтожит его".

(В современной программе C++). Необработанный указатель или ссылка говорит: "Я не владею плацдармом, я просто наблюдаю за ним. Кто-то другой несет ответственность за его уничтожение".

В вашем случае использование unique_ptr для типа члена означает, что MyClass принадлежит объект MyResource. Если геттер должен передать право собственности (то есть, если MyClass отказывается от ресурса для того, кто вызвал геттер), то возвращается unique_ptr (и вам нужно будет return std::move(resource); передача прав собственности явно).

Если получатель не должен отказываться от права собственности (что я считаю вероятным сценарием), просто верните простой старый указатель (если возвращать нулевой указатель является опцией) или простой старой ссылкой (если возврат null не является вариантом),

Ответ 2

У вас есть несколько вариантов здесь, в зависимости от семантики, которую вы хотите, чтобы ваш класс наблюдал.

  1. Вы хотите отказаться от владения своим ресурсом:

    std::unique_ptr<MyResource> MyClass::releaseResource() {
        return std::move(this->resource);
    }
    
  2. Вы хотите сохранить уникальное право собственности, но кто-то еще его использует:

    MyResource& MyClass::getResource() {
        assert(this->resource);
        return *(this->resource);
    }
    
  3. Вы хотите поделиться собственностью, поэтому ресурс не будет уничтожен, если MyClass выходит за рамки: переключите все на std::shared_ptr<MyResource> и по-прежнему возвращайтесь по значению.