После появления новых возможностей в C++ таких как std::make_shared() и std::make_uniqu
то возникает вопрос : А есть ли хоть один случай, когда действительно нужно работать с сырым указателем?
В этом вопросе я не учитываю случаи, когда стороняя библиотека в каком-либо из методов принимает указатель.
Я беру среднего по уровню программиста на C++. Он пишет свою библиотеку без использовани
сторонего кода. И у меня не находится ни одного примера, когда ему действительно нужно пользоваться сырыми указателями.
Ответы
Ответ 1
Во внутренних деталях реализации, когда владеющие указатели усложняют взаимодействие
когда нужно разделять владение, но время жизни объекта чётко детерминировано и не возникае
вопроса: где и когда чистить объект (shared_ptr в таких случаях - лишнее), когда ссылкой не обойтись, потому как возможна ситуация с nullptr у объекта. В публичных API стараться избегать, пока это возможно, либо чётко обосновывать - "почему?" и "зачем?".
В общем, я придерживаюсь правила: обходиться без сырых указателей, пока это возможно. Пока не подводило (embedded).
Кстати, возможно забавно, но в C проектах, при достижении определённого уровня сложности
тоже начинают появляются механизмы разделяемого владения. Это всем известные xxx_ref(object)/xxx_unref(object)
Примеры: GLib со своим gobject, FFmpeg активно внедряет подсчёт ссылок для AVPacket и AVFrame (для таких случаев в Boost существует intrusive_ptr), ядро Linux тоже не стоит в стороне (https://lwn.net/Articles/336224/ по слову Reference Counting или http://www.makelinux.net/books/lkd2/ch17lev1sec7) со своим kobject.
Ответ 2
Самый банальный пример — дерево. Каждый узел хранит родителя. Можно, конечно, хранит
в weak_ptr, но это не удобно и, на мой взгляд, глупо. Поэтому в этом случае используетс
«голый» указатель. Можно придумать и другие примеры, но суть их будет следующая: «голые» указатели, в современном коде, можно и нужно использовать тогда, когда мы не владеем тем, на что ссылаемся и у нас есть уверенность, что то, на что мы ссылаемся не «умрёт» раньше, чем мы.
На эту тему есть отличное видео от Страуструпа: Writing Good C++14. Львиная его доля посвящена именно указателям.
Ответ 3
Упомянутые "умные" указатели являются владеющими. Т.е. при вызове деструктора умног
указателя данные либо освобождаются сразу (std::unique_ptr), либо уменьшается счетчик владения (std::shared_ptr), и при достижении нуля осуществляется освобождение данных.
Если же указатель не владеет данными как раз имеет смысл использовать сырые указатели
Небольшое исключение это std::weak_ptr - невладеющий указатель, но полученный из std::shared_ptr.
Чаще всего наверное использовать сырые указатели приходится при взаимодействии со старым (до C++11) кодом или вовсе Си-кодом. Например, работа со строками char*.
Ответ 4
Хотите простейший пример? :)
int main(int , char**)
Обойтись можно без многого, просто бывают ситуации, когда этот обход куда дольше, чем прямая дорога.
Ответ 5
Те же std::shared_ptr занимают в два раза больше памяти (из-за указателя на счетчик)
Для структур (деревьев, например), активно использующих указатели, это может быть значительной добавкой. Да и передача их по значению - это копирование в стек в два раза большего объёма данных.
Да, в больших проектах часто не так заметно будет это потребление памяти, но бывают и исключительные ситуации.
Комментариев нет:
Отправить комментарий