В основном это касается второй строки: лучшие практики, назначения, параметры функций и т. Д.
Общая практика. Попробуйте сделать все, const
что вы можете. Или, говоря иначе, сделайте все const
для начала, а затем удалите точно минимальный набор const
s, необходимый для работы программы. Это будет большим подспорьем в достижении константности и поможет избежать появления незаметных ошибок, когда люди попытаются заняться вещами, которые они не должны изменять.
Избегайте const_cast <>, как чума. Есть один или два законных варианта использования, но их очень мало и они далеко друг от друга. Если вы пытаетесь изменить const
объект, вам будет гораздо лучше найти того, кто объявил об этом const
в первом темпе, и обсудить этот вопрос с ними, чтобы достичь консенсуса относительно того, что должно произойти.
Что приводит очень аккуратно в назначениях. Вы можете назначить что-то, только если это неконстантно. Если вы хотите присвоить что-то, что является постоянным, см. Выше. Помните , что в декларации int const *foo;
и int * const bar;
разные вещи const
- другие ответы здесь покрыли этот вопрос превосходно, поэтому я не буду вдаваться в подробности .
Параметры функции:
Передача по значению: например, void func(int param)
вам не важно, так или иначе на вызывающем сайте. Можно привести аргумент, что существуют варианты использования для объявления функции как, void func(int const param)
но это не влияет на вызывающего, только на саму функцию, в том смысле, что любое переданное значение не может быть изменено функцией во время вызова.
Передайте по ссылке: например, void func(int ¶m)
теперь это имеет значение. Как только что заявлено func
, разрешено изменять param
, и любой вызывающий сайт должен быть готов справиться с последствиями. Изменение декларации, чтобы void func(int const ¶m)
изменить контракт, и гарантии, которые func
теперь не могут измениться param
, то есть то, что передано, то, что вернется. Как уже отмечали другие, это очень полезно для дешевой передачи большого объекта, который вы не хотите менять. Передача ссылки намного дешевле, чем передача большого объекта по значению.
Проходит указатель: например , void func(int *param)
и void func(int const *param)
эти два довольно много синонимов их позиционные коллегами, с той оговоркой , что вызываемая функция в настоящее время необходимо , чтобы проверить , nullptr
если некоторые другие договорные гарантии уверяют , func
что он никогда не получит nullptr
в param
.
Часть мнения на эту тему. Доказать правильность в таком случае адски сложно, просто чертовски легко ошибиться. Так что не рискуйте, и всегда проверяйте параметры указателя nullptr
. Вы избавите себя от боли и страданий, и вам будет трудно найти ошибки в долгосрочной перспективе. А что касается стоимости проверки, то она очень дешевая, и в случаях, когда статический анализ, встроенный в компилятор, может управлять им, оптимизатор все равно ее исключит. Включите Link Time Generation Generation для MSVC или WOPR (я думаю) для GCC, и вы получите всю программу, то есть даже в вызовах функций, которые пересекают границу модуля исходного кода.
В конце концов, все вышеперечисленное дает веские основания всегда отдавать предпочтение ссылкам на указатели. Они просто безопаснее со всех сторон.