Умные указатели - случаи, когда они не могут заменить исходные указатели

HI,

У меня есть этот запрос о умных указателях.

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

Кто-нибудь может рассказать мне, когда и где они не могут заменить исходные указатели?

Ответ 1

  • Передача указателей на устаревшие API.
  • Обратные ссылки в древовидной структуре с подсчетом ссылок (или любой циклической ситуации, если на то пошло). Этот вопрос спорный, поскольку вы можете использовать слабые ссылки.
  • Итерирование по массиву.

Есть также много случаев, когда вы можете использовать интеллектуальные указатели, но не хотите, например:

  • Некоторые небольшие программы предназначены для утечки всего, потому что это просто не стоит сложной задачи, чтобы выяснить, как очистить после себя.
  • Мелкозернистые пакетные алгоритмы, такие как синтаксические анализаторы, могут выделяться из заранее выделенного пула памяти, а затем просто удалять весь пул по завершении. Наличие интеллектуальных указателей в таком пуле обычно бессмысленно.

Ответ 2

Ярким примером будет API, который будет вызываться из C.

Ответ 3

Зависит от используемого умного указателя. std:: auto_ptr не совместим с контейнерами STL.

Ответ 4

Это вопрос семантики:

  • умный указатель: вы владеете (по крайней мере частично) памятью, на которую указывают, и как таковые ответственны за ее освобождение.
  • регулярный указатель: вам предоставляется дескриптор объекта... или нет (NULL)

Например:

class FooContainer
{
public:
  typedef std::vector<Foo> foos_t;

  foos_t::const_iterator fooById(int id) const; // natural right ?
};

Но вы раскрываете некоторые детали реализации здесь, вы можете отлично создать свой собственный класс итератора... но итератор обычно имеет значение incrementable etc... или использует указатель

class FooContainer
{
public:
  const Foo* fooById(int id) const;
};

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

Конечно, вы также можете использовать weak_ptr здесь (вы получаете метод expired), однако это потребует использования shared_ptr в первую очередь, и вы не можете использовать их в своей реализации.

Ответ 5

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

Ответ 6

Если у вас есть ситуация, когда необработанный указатель прикладывается к intptr_t и обратно по какой-то причине, он не может быть заменен интеллектуальным указателем, потому что операция литья потеряет любую информацию подсчета ссылок, содержащуюся в интеллектуальном указателе.

Ответ 7

Было бы довольно сложно реализовать интеллектуальные указатели, если в какой-то момент вы не используете простые указатели.

Я предполагаю, что было бы сложнее реализовать определенные структуры данных со смарт-указателями. Например, освобождение памяти из регулярного связанного списка довольно тривиально, но подумал бы, чтобы определить комбинацию владеющих и не владеющих интеллектуальными указателями, чтобы получить тот же результат.