Подсистема const одна из самых грязных фич языка C++.
Вроде бы концепция должна быть простой: переменные, декларированные с модификатором const становятся константами, т. е. объектами, которые не может изменить программа. Однако этот термин используется как костыль для починки недостающих возможностей C++, и здесь смысл получается неприятно сложным и иногда разочаровывающе строгим. Далее будут сделаны попытки объяснить, как используется ключевое слово ‘const’, и почему оно вообще существует (перевод статьи [1]).
[Простое использование const]
Простейшее использование const — для декларирования именованной константы. Эта фича C++ была унаследована от языка C.
Чтобы создать декларацию константы, слева от её имени добавляется ключевое слово const. Конечно же, необходимо сразу же инициализировать значение в конструкторе (в момент декларации константы), потому позже по правилам языка мы не имеем права изменить константу. Например,
const int Constant1=96;
Создаст целочисленную константу, из-за отсутствия воображения названную как ‘Constant1’, со значением 96.
Константы. Ключевое слово const. C++ для начинающих. Урок #6.
Такие константы полезны для параметров, которые используются в программе, если их не надо изменять после того, как программа скомпилирована. Достоинство const по сравнению с директивой препроцессора языка C ‘#define’ в том, что компилятор знает о типе константы, и не просто подставляет в нужное место программы нужный текст. Таким образом, при компиляции может быть сделана дополнительная проверка типа, и если что-то не так, то сообщения об ошибке несоответствия типа могут пригодиться.
Это также работает для указателей, но нужно быть осторожным в определении места расположения ключевого слова const, поскольку это повлияет на то, что именно будет константой — или сам указатель будет константой, или то место будет константой, на которое указатель указывает. Это вводит некоторую путаницу, но разобраться просто, если помнить, что const применяется к тому элементу выражения, слева от которого стоит. Например, выражение
const int * Constant2
декларирует указатель именем Constant2, который указывает на какое-то постоянное значение типа int. Т. е. сам указатель изменять можно, но значение, на которое указывает указатель, изменять нельзя. Вот альтернативная запись того же самого (подробнее см. [2]):
int const * Constant2
А это выражение:
int * const Constant3
декларирует, что Constant3 является постоянным указателем на некоторую переменную int. Т. е. значение указателя будет всегда неизменным, а значение переменной, на которую указывает указатель, менять можно. И следующее выражение:
int const * const Constant4
декларирует, что Constant4 является постоянным указателем, указывающим на постоянный int. Просто запомните, что ‘const’ прикладывается непосредственно к объекту справа от const (кроме случая, когда справа от const нет ничего; тогда const прикладывается непосредственно к тому, что слева от него).
[Использование const в возвращаемых значениях функции]
Переменные в JAVASCRIPT. Константы. Ключевые слова LET CONST VAR. Уроки JAVASCRIPT с нуля 2020
Из возможных комбинаций указателей и const, когда постоянный указатель указывает на переменную. Это полезно для ячеек хранения, которые можно изменить, но их положение в памяти (адрес) не меняется.
Еще полезнее указатель (постоянный или нет), указывающий на ‘const’ значение. Это полезно для возврата постоянных строк и массивов из функции, потому что эти строки и массивы реализованы как указатели, и иначе программа могла бы их случайно попытаться изменить и разрушить. Вместо трудной задачи найти место сбоя в программе, попытка изменить неизменяемое значение будет обнаружена еще во время компиляции.
Например, если функция, возвращающая постоянную строку ‘Some text’ написана так:
char *Function1() return «Какой-то текст»;>
то программа потерпит сбой, если случайно поменяет значение примерно так:
Function1()[1]=’a’;
В то время как компилятор сразу нашел бы ошибку, если бы функция была написана с ключевым словом const:
const char *Function1() < return «Какой-то текст»;>
потому что компилятор знает о том, что возвращенное функцией значение поменять нельзя.
[Когда это становится «грязным» — в передаче параметра]
Когда подпрограмма или функция вызывается с параметрами, то переменные, переданные как параметры, могут быть использованы не только для передачи данных в функцию, но еще и для целей возврата обработанных данных из функции. Некоторые языки разрешают такую фичу специальным синтаксисом, как например добавлением типов параметров ‘in:’, ‘out:’ и ‘inout:’, в то время как на языке C нужно работать на более низком уровне, и указывать метод передачи переменных, выбрав такой, который разрешает нужное направление перемещения данных.
Например, подпрограмма наподобие такой:
void Subroutine1(int Parameter1)
принимает целочисленный параметр Parameter1 способом по умолчанию для языков C и C++ — в подпрограмму передается копия передаваемого объекта. Таким образом, подпрограмма может прочитать значение переданной переменной, но подпрограмма никак не может повлиять на этоу переменную, потому что все изменения переданного параметра внутри функции будут производится на копии, и эти изменения потеряются, когда функция завершит свою работу. Например, если подпрограмма написана так:
void Subroutine2(int Parameter1) < Parameter1=96;>
то по завершению работы функции переданная в параметре переменная останется неизмененной, она не будет установлена в значение 96.
Добавление символа ‘ перед именем переменной в коде программы генерируют в языке C указатели!) приведет к тому, что в подпрограмму (или функцию) будет передана не копия переменной, а ссылка на неё. Т. е. внутри функции будет использоваться сама переменная, так что функция может её поменять. Таким образом, если подпрограмма написана так:
void Subroutine3(int Parameter1=96;>
то она установит на выходе переданную переменную в значение 96. Этот метод передачи переменной не как копии называется на языке ‘ссылкой’ (reference).
Передача переменных по ссылке является дополнением языка C++, которого не было в C. Чтобы передать изменяемую переменную на оригинальном C, использовалась передача указателя на переменную. Тогда внутри тела функции появляется возможность поменять внешнюю по отношению к функции переменную, которая передана в параметре через указатель. Пример:
void Subroutine4(int *Parameter1) < *Parameter1=96;>
Это будет работать (в том числе и на C++), но синтаксис получается довольно громоздким.
Но как здесь может быть использовано ‘const’? Ну в общем есть второй способ передать данные по ссылке или указателю вместо копии. Достоинство этого второго метода — экономия памяти, когда копирование переменной заняло бы слишком много памяти. Особенно это полезно использовать вместе с большими типами переменных (например, с определенными пользователем структурами на C или классами на C++). Чтобы экономить память и не копировать передаваемые переменные, подпрограмма может быть декларирована так:
void Subroutine4(big_structure_type
Но здесь возникает проблема, потому что использование ‘Parameter1);
то это заставит компилятор передать переменную как есть, не копируя, но кроме этого запретит её изменение в теле функции. Это выглядит грязным, потому что по сути искусственно превращает доступ к переменной на только на чтение, хотя цель этого всего состояла в трюке заставить компилятор выполнить некоторую оптимизацию по экономии памяти (обычно в стеке).
В идеале программист не должен был бы точно детализировать, как переменная передается, ему нужно было бы просто указать направление передачи данных, и оставить для самого компилятора задачу оптимизировать код. Но язык C был специально разработан в расчете на сырое, низкоуровневое программирование (C еще иногда называют «интеллектуальным ассемблером») — чтобы программы могли эффективно работать даже на намного менее мощных компьютерах, чем те, что распространены сейчас. Таким образом, программист все еще должен явно задавать такие моменты в своем коде.
[Грязнее грязного — в Объектно-Ориентированном Программировании]
В ООП вызов ‘метода’ (это теперь так называется функция в стиле ООП) объекта имеет дополнительное усложнение. Кроме доступа к переменным в списке параметров метода, метод имеет доступ к полям (или членам, т. е. переменным) самого объекта класса, которые всегда передаются непосредственно, не как копии. Например, простейший класс Class1, определенный так:
class Class1 < void Method1(); int MemberVariable1;>
не имеет вообще никаких явных параметров для метода Method1, но вызов Method1 в этом классе мог бы поменять значение члена класса MemberVariable1. Например, так:
void Class1::Method1() < MemberVariable1=MemberVariable1+1;>
Решение состоит в том, чтобы добавить const после списка параметров:
class Class2 < void Method1() const; int MemberVariable1;>
Это запретит методу Method1 в классе Class2 изменять какие бы ни было члены в объекте этого класса.
И конечно, иногда нужно комбинировать некоторые из этих разных использований ключевого слова const, что может ввести в конфуз:
const int*const Method3(const int*const
В этом примере целых 5 раз было использовано ключевое слово const, что означает следующее: переменная, на которую будет указывать возвращенный из метода Method3 указатель, менять нельзя. Нельзя также менять и сам возвращенный указатель. Причем переданный в метод указатель не будет изменен, как и значение, на который указывает, не может быть изменено, и Method3 не имеет права изменять поля своего класса!
[Неудобства от const]
Помимо запутывающего синтаксиса const, есть другие полезные фичи, которыми система может ограничивать действия выполняемой программы.
Кое-что в программировании на C++ раздражает, когда нужно оптимизировать программу по скорости. Например, метод, объявленный как const, не может даже внести изменения в скрытые части своего объекта, которые все равно были бы не видны снаружи.
Это включает сохранение промежуточных результатов долгих вычислений, которые сохранили бы время обработки в последующих вызовах методов класса. Вместо этого нужно либо передавать эти промежуточные результаты обратно в вызывающий код, чтобы потом их передать снова в подпрограмму (что грязно) или все вычислять заново в каждом вызове (что не эффективно). В поздних версиях C++ было добавлено ключевое слово mutable, которое разрешает отменить ограничение ‘const’ для этой цели. Это возлагает ответственность на программиста — как он действительно будет использовать константы. Так что если Вы пишете программу, где есть какой-то класс, использующий mutable, то у Вас уже нет гарантии, что константы действительно останутся постоянными во всех случаях, так что ключевое слово виртуально становится бесполезным.
Нельзя просто избегать использования const в методах класса, потому что const заразная. Объект, который сделан как const, например будучи переданным как параметр способом ‘const http://microsin.net/programming/pc/cpp-const-declaration-why-and-how.html» target=»_blank»]microsin.net[/mask_link]
Нужно проверить тест по информатике введение в программирование
Там где / тот ответ я выбрал
Вопрос № 13
Дана программа:
Uses Crt;
var a:integer;
b:real;
begin
b:=1.5;
a:=b;
end.
В какой строчке ошибка?
Да
Нет/
Вопрос № 15
Выберите ВЕРНОЕ утверждение (их может быть одно или несколько):
Если в программе используется переменная, она должна быть описана в разделе Var./
Переменной целого типа можно присвоить значение вещественного типа.
После begin необходима точка с запятой.
Оператор вывода информации (текста или значения переменной) — Write или Writeln./
Вопрос № 16
Выберите ВЕРНОЕ утверждение (их может быть одно или несколько):
Если в программе нет констант, то использование слова Const не обязательно. /
Если в программе нет условий и циклов, то команды выполняются одна за другой. /
Использование в заголовке строчки Program не обязательно.
Программа заканчивается строчкой end;/
Вопрос № 17
Дано несколько команд языка Pascal, осуществляющие вывод на экран.
1) Writeln(a);/
2) Writeln(`x равно: `,x);/
3) Writeln(`Результат равен, Res);
4) Writeln(`Привет! `);/
Отметьте правильно написанные команды:
Вопрос № 18
В разделе описания программы описаны две переменных:
В самой программе переменной m присваивается значение квадратного корня из 16.
Выберите ПРАВИЛЬНО написанные варианты команд (их может быть один или несколько):
n:=0;m:=sort(16);
n:=16; m:=sqrt(n);/
n:=sqrt(256); m:=sqrt(n);/
n:=20-5; m:=sqrt(n);
Вопрос № 19
Какое число выводит на экран фрагмент программы?
a:=32;
b:=16;
c:=(a+b)/2;
d:=a+b-c/4;
writeln(d);
Ответ: 42
Источник: znanijam.net
Константы в Java
Константа — постоянное значение, известное до начала работы программы и заданное в коде один раз.
Почему это удобно:
- Если вы используете значение многократно, а в ходе разработки его потребуется изменить, достаточно будет одной правки.
- Вместо длинного значения можно ставить в коде короткое имя константы.
- Нет риска ошибиться при очередном вводе значения.
По логике это надо бы называть «постоянной» — в противоположность переменной, — но традиция уже сложилась.
Константа может хранить число, строку, символ, ссылку на объект и др. Значение константы еще называют литералом (от англ. literal — буквальный), потому что его записывают как есть — без предварительных вычислений.
При объявлении констант в Java используют ключевое слово final — оно показывает, что литерал не должен меняться. Именовать константы принято заглавными буквами со знаком подчеркивания вместо пробела: ВОТ_ТАК.
Пример строковой константы:
public static final String MY_CONSTANT=»Мой текст»; //создаем строку и присваиваем ей постоянное значение
Модификаторы public и static означают, что перед нами публичная константа уровня класса — без привязки к отдельным объектам, классам и т.д. Это аналог глобальной константы в Java. Значение константы всегда указывают при её создании. Если инициализация отложена, перед нами не константа, а «финальная переменная». Её значение тоже обычно задают только один раз, но:
- оно может быть получено в результате вычислений;
- если внутри финальной переменной лежит объект, его свойства можно менять, т.к. финализация действует на ссылку, а не на значение.
Важно следить, чтобы значение константы нигде не конфликтовало с логикой вычислений. Например, скорость звука может быть константой в одной среде, но в разных средах она разная. Если в коде мы сравниваем что-то со скоростью звука, хорошим вариантом будет создать финальную переменную, значение которой можно будет переопределять в зависимости от среды.
Неименованные константы в Java
Неименованная константа — постоянное произвольное значение, которое вносят в код однократно:
if (i 5 ) // 5 — это константа;
Если значение нужно использовать ещё где-то, лучше вынести его в именованную константу или финальную переменную.
Константы встроенных классов Java
Класс Integer в Джаве отвечает за обработку целых чисел типа int. Ограничителями диапазона значений int служат константы MIN_VALUE (минимальное значение) и MAX_VALUE (максимальное). Константы с теми же именами существуют и в остальных классах для обработки числовых данных: byte, long, float, double. При создании объекта нужного типа классы обращаются к пулам — массивам констант Java, где хранятся допустимые элементы диапазона.
Где хранить константы
Новички часто спрашивают, допустимо ли держать константы в интерфейсе или обязательно раскладывать их по классам. Единого ответа нет, но логичнее хранить константы ближе к месту использования. Общие для нескольких не связанных между собой классов константы можно вынести в отдельный класс.
Источник: gb.ru