Умные указатели - случаи, когда они не могут заменить исходные указатели
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
Было бы довольно сложно реализовать интеллектуальные указатели, если в какой-то момент вы не используете простые указатели.
Я предполагаю, что было бы сложнее реализовать определенные структуры данных со смарт-указателями. Например, освобождение памяти из регулярного связанного списка довольно тривиально, но подумал бы, чтобы определить комбинацию владеющих и не владеющих интеллектуальными указателями, чтобы получить тот же результат.