зачем нужен const c

Многоликий const

Ключевое слово const — одно из самых многозначных в C++. Правильно использование const позволяет организовать множество проверок ещё на этапе компиляции и избежать многих ошибок из числа тех, которые бывает трудно найти при помощи отладчиков и/или анализа кода.

Первая половина заметки рассчитана скорее на начинающих (надеюсь мнемоническое правило поможет вам запомнить, где и для чего используется const), но, возможно, и опытные программисты смогут почерпнуть интересную информацию о перегрузке методов по const.

Константы и данные

Самый простой случай — константные данные. Возможно несколько вариантов записи:

Все они правильные и делают одно и тоже — создают переменную, значение которой изменить нельзя.

Константы и указатели

При использовании const с указателями, действие модификатора может распространяться либо на значение указателя, либо на данные на которые указывает указатель.

Работает (const относится к данным):

Тоже самое и тоже работает:

А вот это уже не работает:

Если бы операция присвоения изменяла бы не указатель, а данные:

то ситуация была бы диаметрально противоположной.

Существует мнемоническое правило, позволяющее легко запомнить, к чему относится const. Надо провести черту через «*», если const слева, то оно относится к значению данных; если справа — к значению указателя.

Ну и конечно, const можно написать дважды:

Константы и аргументы/результаты функций

C функциями слово const используется по тем же правилам, что при описании обычных данных.

Константы и методы (перегрузка)

А вот с методами есть одна тонкость.

Во-первых, для методов допустимо использование const, применительно к this. Синтаксис таков:

Кроме того, этот const позволяет перегружать методы. Таким образом, вы можете писать оптимизированные варианты методов для константных объектов.

То есть для константного объекта (с x=2) был вызван соответствующий метод.

Осталось только добавить, что если вы планируете использовать const-объекты, то вам надо обязательно реализовать const-методы. Если вы в этом случае не реализуете не-const-методы, то во всех случаях будут молча использоваться const-методы. Одним словом, const лучше использовать там, где это возможно.

И ещё… я собрался в отпуск… возможно, не смогу ответить на комментарии до понедельника-вторника. Не сочтите за невнимание 🙂

Источник

const (C++)

При изменении объявления данных const ключевое слово указывает, что объект или переменная не являются изменяемыми.

Синтаксис

Значения-константы

const Ключевое слово указывает, что значение переменной является константой и сообщает компилятору о том, что программист не сможет его изменить.

В C++ const вместо директивы препроцессора #define можно использовать ключевое слово, чтобы определить постоянные значения. Значения, определенные с помощью, const подчиняются проверке типа и могут использоваться вместо константных выражений. В C++ можно указать размер массива с помощью const переменной следующим образом:

В языке C константные значения по умолчанию имеют внешнюю компоновку, поэтому они могут использоваться только в файлах исходного кода. В языке C++ константные значения по умолчанию имеют внутреннюю компоновку, которая позволяет использовать их в файлах заголовков.

const Ключевое слово также можно использовать в объявлениях указателей.

Указатели на данные-константы можно использовать в качестве параметров функций, чтобы функция не могла изменять параметр, переданный посредством указателя.

Для объектов, не объявленных как константы, можно вызывать как константные, так и неконстантные функции-члены. Можно также перегружать функцию-член с помощью const ключевого слова; это позволяет вызывать другую версию функции для постоянных и неконстантных объектов.

Нельзя объявлять конструкторы или деструкторы с const ключевым словом.

Функции-члены-константы

Объявление функции-члена с помощью const ключевого слова указывает, что функция является функцией «только для чтения», которая не изменяет объект, для которого она вызывается. Функция-член константы не может изменять какие-либо нестатические элементы данных или вызывать функции-члены, не являющиеся константами. Чтобы объявить функцию-член константы, поместите const ключевое слово после закрывающей скобки списка аргументов. const Ключевое слово требуется как в объявлении, так и в определении.

Различия констант C и C++

При объявлении переменной, как const в файле исходного кода на языке C, это можно сделать следующим образом:

Затем эту переменную можно использовать в другом модуле следующим образом:

Но чтобы получить такое же поведение в C++, необходимо объявить const переменную как:

Если вы хотите объявить extern переменную в файле исходного кода C++ для использования в файле исходного кода на языке C, используйте:

для предотвращения изменения имени компилятором C++.

Remarks

При использовании списка параметров функции-члена const ключевое слово указывает, что функция не изменяет объект, для которого она вызывается.

Дополнительные сведения о const см. в следующих разделах:

Источник

Как пользоваться const в C++?

Введение

Реклама

Переменные и const

Наиболее простой и интуитивно понятный вариант использования const заключается в объявлении константных значений:

Похожего результата можно добиться с помощью макросов:

Но вариант с макросом не столь хорош, поскольку не дает возможности указать тип переменной. Из-за возможных проблем с типизацией лучше пользоваться константами, а не макросами. Более того, макросов лучше и вовсе избегать. В C++ реализована прекрасная поддержка шаблонных функций и классов, которые в большинстве случаев представляют более надежную альтернативу. Однако стоит признать, что бывают случаи, когда макросы оказываются полезными. Но сейчас речь не о них.

А что, если мы по какой-то причине не может пользоваться C++11? И в этом случае можно легко объявить константный вектор:

То есть для сложных типов, которые не получается заполнить в одну строку, достаточно вынести компоновку в отдельную функцию для инициализации. С другой стороны, мы могли бы объявить вектор в функции makeVector() с ключевым словом static и вместо константы использовать саму функцию. Но это уже дело вкуса:

Константная ссылка объявляется схожим образом:

Суть константных ссылок заключается в том, что мы получаем доступ к значению переменной, на которую сделана ссылка, но изменить ее не имеем права. Основное назначение константных ссылок заключается в передаче входных параметров функциям. Но об этом немного позже.

Для указателей существует три варианта использования const :

В варианте 1 мы получили указатель, который можно использовать как более гибкую константную ссылку. Он работает почти так же, но мы можем в любой момент сослаться на другую переменную. Вариант 2 работает так же, как обычная ссылка. Значение менять можно, а указать на другую переменную не выйдет. И наконец вариант 3. Он равносилен случаю константной ссылки. То есть один раз объявили указатель и ничего больше менять не можем.

В первом и втором варианте вполне можно обойтись использованием ссылок. Особой разницы нет. Для третьего ограничиться ссылкой получится не всегда. Например:

Строку в стиле C с помощью ссылки мы объявить не сможем. Нужен указатель. И он должен быть константным, поскольку изменение содержания строки запрещено и приведет к неопределенному поведению. А второй const здесь не помешает, чтобы получить жесткую привязку указателя к заданному значению и запретить случайные присвоения:

Реклама

Функции и const

Если же вы хотите передать в функцию объект структуры или класс, то используйте константную ссылку:

Каноничным примером на этот случай является конструктор копирования:

Если бы мы попытались передать в конструктор копирования не ссылку, а значение, то для инициализации этого значения нам пришлось бы вызвать конструктор копирования, который мы и хотим реализовать.

Еще const можно использовать для объявления константных функций-членов классов:

Но тут есть один тонкий момент. Иногда бывает полезно инкапсулировать информацию о том, что на самом деле внутреннее состояние класса меняется, но все равно объявить функцию-член константной. Например, в многопоточной среде мы можем использовать мьютексы:

Заключение

Источник

Урок №123. Классы и const

Обновл. 13 Сен 2021 |

На уроке №37 мы узнали, что фундаментальные типы данных (int, double, char и т.д.) можно сделать константными, используя ключевое слово const, и что все константные переменные должны быть инициализированы во время объявления. В случае с константными фундаментальными типами данных инициализация может быть копирующей, прямой или uniform:

Константные объекты классов

Объекты классов можно сделать константными (используя ключевое слово const). Инициализация выполняется через конструкторы классов:

Как только константный объект класса инициализируется через конструктор, то любая попытка изменить переменные-члены объекта запрещена, так как это нарушает принципы константности объекта. Запрещается как изменение переменных-членов напрямую (если они являются public), так и вызов методов (сеттеров), с помощью которых можно установить значения переменным-членам. Рассмотрим следующий класс:

Строки №16-17 вызовут ошибки компиляции, так как они нарушают принципы константности объекта, пытаясь напрямую изменить переменную-член и вызывая сеттер для изменения значения переменной-члена.

Константные методы классов

Теперь рассмотрим следующую строку кода:

Удивительно, но это также вызовет ошибку компиляции, хотя метод getValue() не делает ничего для изменения переменной-члена! Оказывается, константные объекты класса могут явно вызывать только константные методы класса, а getValue() не указан, как константный метод. Константный метод — это метод, который гарантирует, что не будет изменять объект или вызывать неконстантные методы класса (поскольку они могут изменить объект).

Чтобы сделать getValue() константным, нужно просто добавить ключевое слово const к прототипу функции после списка параметров, но перед телом функции:

Теперь getValue() является константным методом. Это означает, что мы можем вызывать его через любой константный объект.

Для методов, определенных вне тела класса, ключевое слово const должно использоваться как в прототипе функции (в теле класса), так и в определении функции:

Кроме того, любой константный метод, который пытается изменить переменную-член или вызвать неконстантный метод класса, также приведет к ошибке компиляции, например:

Обратите внимание, конструкторы не могут быть константными. Это связано с тем, что они должны иметь возможность инициализировать переменные-члены класса, а константный конструктор этого не может сделать. Следовательно, в языке С++ константные конструкторы запрещены.

Стоит отметить, что константный объект класса может вызывать конструктор, который будет инициализировать все или некоторые переменные-члены, или же не будет их инициализировать вообще!

Правило: Делайте все ваши методы, которые не изменяют данные объекта класса, константными.

Константные ссылки и классы

Еще одним способом создания константных объектов является передача объектов в функцию по константной ссылке.

На уроке №98 мы рассмотрели преимущества передачи аргументов по константной ссылке, нежели по значению. Если вкратце, то передача аргументов по значению создает копию значения (что является медленным процессом). Большую часть времени нам не нужна копия, а ссылка уже указывает на исходный аргумент и является более эффективной, так как избегает создания и использования ненужной копии. Мы обычно делаем ссылку константной для гарантии того, что функция не изменит значение аргумента и сможет работать с r-values (например, с литералами).

Можете ли вы определить, что не так со следующим кодом?

Источник

Const и оптимизации в C

Рассмотрим такую программу:

Функция foo принимает указатель на const, который обещает от имени автора foo что значение x не будет изменено. Может показаться, что компилятор может предположить, что x всегда равен нулю, а значит и y тоже.

Важно помнить, что const — не значит константный. Возьмите себе на заметку, что это неправильное название. Это не инструмент для оптимизации. Он нужен чтобы информировать программиста — а не компилятор — как инструмент, помогающий поймать определенный класс ошибок во время компиляции. Мне нравится, когда его используют в API потому что он сообщает, как функция будет использовать свои аргументы, или как вызывающий должен обращаться с возвращенными указателями. Обычно он недостаточно строгий, чтобы изменить поведение компилятора.

Несмотря на то, что я сказал, иногда компилятор может воспользоваться const для оптимизации. В спецификация C99, в §6.7.3¶5, есть одно предложение об этом:

Одним изменением в bar я могу сделать это правило применимым, позволяя оптимизатору поработать.

Загрузка исчезает, y исчезает, и функция всегда возвращает ноль.

Любопытно, что спецификация позволяет компилятору пойти еще дальше. Он может разместить x где-нибудь вне стека, даже в read-only памяти. Например, он может произвести такую трансформацию:

Или на x86-64 (-fPIC, модель малой памяти), где получается избавиться от еще нескольких инструкций:

Ни clang, ни gcc не заходят так далеко, видимо потому, что это более опасно для плохо написанного кода.

Даже со специальным правилом о const rule, используйте const для себя и своих товарищей-программистов. Пусть оптимизатор сам для себя решает, что константно, а что нет.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *