Какой самый чистый способ определения указателя без удаления? - PullRequest
3 голосов
/ 18 апреля 2019

Недавно я наткнулся на старую C-функцию, возвращающую указатель на статический массив.Я написал обертку вокруг этой функции и возвратил std::unique_ptr, который использует no-delete, чтобы подчеркнуть тип возвращаемого указателя - предупреждение «не удаляй меня» для пользователя.Вот пример кода

 extern "C" int *f(int i);

 struct noop
 {
      template <typename T>
      void operator() (T t) const noexcept
      {
      }
 };
 class MyClass
 {
     public:          
     std::unique_ptr<int, noop> F(int value) const 
      { 
            return std::unique_ptr<int, noop>(f(value));
      }
 };

Есть ли более чистый способ сделать это без определения структуры без удаления?

Ответы [ 2 ]

7 голосов
/ 18 апреля 2019

[..] старая C-функция, возвращающая указатель на статический массив. я написал обертка вокруг этой функции и вернула std::unique_ptr

Не . Возвращаясь std::unique_ptr говорит вызывающему:

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

Ничего из этого не верно для указателя на статический массив!

Придерживайтесь необработанного указателя или используйте некоторый класс-оболочку, чтобы разрешить ссылочный доступ. std::reference_wrapper для предоставления семантики, например, необработанного указателя при копировании.

0 голосов
/ 22 апреля 2019

Рекомендации по кодированию на C ++ предлагают использовать псевдонимы или "фиктивные" оболочки для указания владельца или ненулевого значения:

. Для их реализации необходимо иметьпосмотрите на:

https://github.com/Microsoft/GSL/blob/master/include/gsl/pointers

Вы увидите пример owner<> и non_null<>.

Вы можете подобрать определение.Очевидно, что не принадлежащий указатель не должен быть удален;если вам просто нужно напоминание, тогда

template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
using non_owner = T;

и если вы хотите принудительного применения, скопируйте и адаптируйте код для non_null<> по ссылке.

...