Я часто во время код ревью и менторства новичков замечаю, что большинство не понимает как на самом деле работает const. Более того, Си и С++ содержат синтактический сахар, позволяющий писать const перед объявлением переменной - это только путает.
const - указывает, что выражением перед ним - константно. То есть правильная запись выглядит вот так:
int a = 42;
int const b = a; // переменная b неизменяемого типа int, с значением a;
int const * const c = &a; // неизменяемый указатель с незменяемым значением;
c = &b; // ошибка компиляции! указатель запрещено менять.
*c = 99; // ошибка компиляции! значение по адресу запрещено менять.
Именно из-за того, что const действует на впередистоящее выражение, константные методы класса объявляются с констом в конце объявления, а не в начале:
int getSomeProperty() const;
А объявления перменных с констом в начале это всего лишь синтактический сахар и он довольно часто путает новичков
const int ** ppbuffer; // Спроси новичка что из этого константно, и он не сможет дать уверенного ответа.
Автор, если можешь, используй const без сахара, так молодые программисты будут делать меньше ошибок и нам будет легче на код-ревью.
Я сам так же с сахара начинал, думаю все так начинали, потому что все учебники так написаны. Но пересмотрел свои взгялды на "жизнь" когда начал встречать в коде многоэтажные выражения с констами и указателями.
https://ru.wikipedia.org/wiki/Синтаксический_сахар
Разница лишь в чтении сложных конструкций. То что показано в посте довольно наглядно и работает соврешенно правильно и понятно. Но глядя на конструкцию
const int ** ppbuffer
Новичкам трудно сходу сказать, что именно в этой констукции константно, сам указатель, значение указателя или значение значения указателия, или всё сразу. Кстати говоря, эта конструкция называется двойным указателем, указатель на указатель. На практике редко применяется в C++, чаще используется в Си так как там нет ссылок.
При записи const как подобает не будет возникать путанницы
int a = 42;int *pnode = &a;
int const * const * const ppbuffer = &pnode;
Первый конст относится к конечному месту назначения, куда ведут указатели - памяти занятой перменной a.
Второй конст относится к pnode.
Третий собственно к самому указателю ppbuffer.
Поставив конст в нужное место можно управлять тем, что должно меняться, а что должно оставаться неизменным.