Вопрос

Я пытаюсь "модернизировать" некоторый существующий код.

  • У меня есть класс, который в настоящее время имеет переменную-член "Device* device_".
  • Он использует new для создания экземпляра в некотором коде инициализации и имеет "удалить device_" в каталоге деструкции.
  • Функции-члены этого класса вызывают много другие функции, которые принимают устройство* в качестве параметра.

Это работает хорошо, но чтобы "модернизировать" мой код, я подумал, что мне следует изменить переменную, которая будет определена как "std::unique_ptr<Device> device_" и удалите явный вызов delete, что делает код более безопасным и в целом лучше.

Мой вопрос заключается в следующем -

  • Как я должен тогда передать устройство_ переменная для всех функций, которым она нужна в качестве параметра?

Я могу вызвать .get, чтобы получить необработанный указатель при каждом вызове функции.Но это кажется уродливым и лишает смысла некоторые причины использовать unique_ptr в первую очередь.

Или я могу измениться каждый функция работает так, что вместо того, чтобы принимать параметр типа "Device*", она теперь принимает параметр типа "std::unique_ptr& ".Что (для меня) несколько запутывает прототипы функций и затрудняет их чтение.

Какова наилучшая практика для этого?Пропустил ли я какие-либо другие варианты?

Это было полезно?

Решение

в Modern Стиль C ++, есть две концепции клавиш:

    .
  • владение
  • нутряность

Владение о владельце некоторого объекта / ресурса (в этом случае, экземпляр Device). Различные генеракодицетагкод, генеракодицетагкод или генеракодицетагкод составляют владение.

Nululity гораздо проще, однако: он просто выражает, может ли данный объект быть нулевым, и не заботится о чем-либо еще, и, безусловно, не о владении!


Вы были Prange , чтобы переместить реализацию вашего класса в направлении std::unique_ptr (в целом), хотя вы можете захотеть смарт-указатель с глубокой копией семантики, если ваша цель - реализовать PIMPL.

Это четко передает, что ваш класс является единственным, ответственным за этот кусок памяти, и аккуратные сделки со всеми различными способами памяти могут просочиться иначе.


С другой стороны, большинство пользователей из ресурсов не могли заботиться о его собственности.

До тех пор, пока функция не поддерживает ссылку на объект (хранить его в карте или что-то в этом роде), то все, что имеет значение, состоит в том, что срок службы объекта превышает продолжительность вызова функции.

Таким образом, выбирая, как пройти параметр зависит от его возможного Nullity :

    .
  • никогда не нулевой? Пройти ссылку
  • Возможно, нуль? Передайте указатель , простой голый указатель или подобный класс (с ловушкой на нуле, например)

Другие советы

Это действительно зависит.Если функция должна взять на себя ответственность на собственность ustake_ptr, то это подпись должна предпринять unique_ptr<Device> BV значение и вызывающий абонент должен генеракодичевать указку.Если владение не является проблемой, то я бы сохранил подпись указывать на сырое указатель и передаю указатель Unique_ptr с использованием std::move.Это не уродливо , если рассматриваемая функция не берет на себя ответственность.

Я бы использовал std::unique_ptr const&.Использование неконстантной ссылки даст вызываемой функции возможность сбросить ваш указатель.
Я думаю, что это хороший способ выразить, что ваша вызываемая функция может использовать указатель, но ничего больше.
Так что для меня это сделает интерфейс более удобным для чтения.Я знаю, что мне не нужно возиться с переданным мне указателем.

Лучшая практика, вероятно, не использовать std::unique_ptr в этом случае, Хотя это зависит.(Вы обычно не должны иметь более одного сырого указатель на динамически выделенный объект в классе.Хотя это также зависит.) Одна вещь, которую вы не хотите делать в этом случае, это проезжая вокруг std::unique_ptr (и, как вы заметили, Генеракодицетагкод немного громоздкая и запутанная).Если это Является ли единственный динамически выделенный указатель в объекте, я бы просто придерживаюсь С сырой указатель и генеракодицетагкодом в деструктор.Если есть Некоторые такие указатели, я бы рассмотрел по поводу перенаправления каждого из них к Отдельный базовый класс (где они все еще могут быть сырыми указателями).

Это может быть неосуществимо для вас, но замена каждого случая Device* около const unique_ptr<Device>& это хорошее начало.

Вы, очевидно, не умеете копировать unique_ptrs, и вы не хотите его перемещать.Замена ссылкой на unique_ptr позволяет основной части существующих функций продолжать работать.

Теперь это ловушка, вы должны пройти мимо const & чтобы предотвратить действия вызываемых абонентов unique_ptr.reset() или unique_ptr().release().Обратите внимание, что при этом по-прежнему передается изменяемый указатель на устройство.С помощью этого решения у вас нет простого способа передать указатель или ссылку на const Device.

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