Страницы

Поиск по вопросам

вторник, 26 ноября 2019 г.

В каких случаях возникает потребность использования raw pointers в современном C++?


После появления новых возможностей в 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 занимают в два раза больше памяти (из-за указателя на счетчик) Для структур (деревьев, например), активно использующих указатели, это может быть значительной добавкой. Да и передача их по значению - это копирование в стек в два раза большего объёма данных. Да, в больших проектах часто не так заметно будет это потребление памяти, но бывают и исключительные ситуации.

Комментариев нет:

Отправить комментарий