Совместное использование объектов, принадлежащих через смарт-указатель - PullRequest
0 голосов
/ 07 ноября 2018

По сути, у меня есть одна структура, которая содержит объекты для обмена между классами следующим образом:

struct CoreComponents
{
    std::unique_ptr<a> m_A = std::make_unique<a>();
    std::unique_ptr<b> m_B;
    std::unique_ptr<c> m_C = std::make_unique<c>();
};

И в моем основном классе я владею им через unique_ptr ;

class Game
{
    ...
  private:
    std::unique_ptr<CoreComponents> m_Components;
    ...
};

Тогда у меня есть другие n классы, которые мне нужны для доступа к этому m_Components объекту из его функций без создания копий. (я не буду изменять содержимое этого объекта)

Я пытался использовать shared_ptr для хранения m_Components в Game классе, а затем передать его другим классам ( их конструкторам) через значение и сохраните его, но этот сценарий вызывает утечки памяти. (я использую memcheck для проверки утечек) Я узнал, что это причина утечки, но я не мог понять, почему именно.

сценарий Shared_ptr

Конструктор класса, который мне нужен для доступа к объекту CoreComponents;

GameScene::GameScene(std::shared_ptr<CoreComponents> components)
: m_Components(std::move(components))

Я пытаюсь сохранить его как член класса GameScene, а затем использовать его в функциях;

std::shared_ptr<CoreComponents> m_Components;

И вот как я передаю его из класса Game;

auto gs = std::make_unique<GameScene>(m_Components)

Общее использование внутри класса GameScene;

m_Components->m_A->draw(*m_OtherObjectInsideGameScene);

Так, каков наилучший способ создать подобный дизайн, используя современный c ++? Я пытался избежать паттерна синглтона, но нужно ли его использовать для достижения этой цели или это возможно при более эффективном использовании интеллектуальных указателей?

PS: Структура CoreComponents должна быть удалена из памяти при разрушении класса Game.

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

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

Я бы сохранил вашу собственную структуру и создал бы специальные структуры для конкретных пользователей:

struct CoreComponents {
   unique_ptr<A> a; unique_ptr<B> b; ...
};

struct PartOfTheSystem {
  void use(A& a, B& b);
};

struct Game {
  CoreComponents components;
  PartOfTheSystem user;

  void stuff() {
    user.use(*components.a, *components.b);
  }
};

Да: больше печатать.

Но также: очень четкая логика: строительство / владение и использование - это отдельные проблемы, и это совершенно ясно по замыслу! Также см. https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-smartptrparam.

0 голосов
/ 07 ноября 2018

Лучший способ, если у вас есть общие объекты, это действительно использовать shared_ptr.

A unique_ptr для уникального владельца.

Если у вас были утечки памяти, пришло время выяснить, почему это произошло, и исправить их! Ваш отчет предлагает циклическую ссылку. Проверьте случайный лямбда-захват, и в некоторых местах вы, возможно, хотели использовать weak_ptr.

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

...