Кіріспе

Деректерді тек оқуға арналған деп белгілейтін типтік анықтауыш. Кейбір бағдарламалау тілдерінде const – бұл типтік анықтауыш (деректер түріне қолданылатын түйін сөз), деректердің тек оқуға арналғанын көрсетеді. Бұл тұрақтыларды жариялау үшін қолданылғанымен, C тілдер отбасындағы басқа тілдердегі ұқсас құрылымдардан өзгешеленеді, себебі ол типтің бір бөлігі болып табылады, сондықтан көрсеткіштермен, сілтемелермен, күрделі деректер түрлерімен және типтік тексерумен біріктірілгенде күрделі әрекет етеді. Басқа тілдерде деректер бір жад орынында сақталмайды, әр қолданылу үшін компиляция уақытында көшіріледі. Оны қолданатын тілдерге C, C++, D, JavaScript, Julia және Rust жатады.

Кіріспе

Объектіні жариялау кезінде қолданылғанда, бұл объектінің тұрақты екенін көрсетеді: оның мәні өзгертілмейді, айнымалыдан өзгеше. Бұл негізгі қолданылу – тұрақтыларды жариялау – көптеген басқа тілдерде де кездеседі. Дегенмен, басқа тілдерден айырмашылығы, C тілдер отбасында const түрінің бөлігі болып табылады, объектінің бөлігі емес. Мысалы, C-де `int const x` жариялағанда, `const` түрінің бөлігі болып есептеледі, яғни `(int const) x` деп талданғандай. Ал Ada-да `X : INTEGER` тұрақтысы (объектінің бір түрі) жарияланады: тұрақты объектінің бөлігі, бірақ түрінің бөлігі емес. Бұл екі нәтижеге әкеледі. Біріншіден, `const` күрделі типтің бөліктеріне қолданылуы мүмкін – мысалы, `int const * const x` тұрақты бүтін санға тұрақты сілтемені жариялайды, ал `int const * x` тұрақты бүтін санға өзгермелі сілтемені жариялайды, ал `int * const x` өзгермелі бүтін санға тұрақты сілтемені жариялайды. Екіншіден, `const` түрінің бөлігі болғандықтан, типті тексеру кезінде оған сәйкес келуі керек. Мысалы, келесі код жарамсыз:
```
void f(int& x);
int const i;
f(i);
```
өйткені `f` функциясының аргументі өзгермелі бүтін сан болуы керек, бірақ `i` – тұрақты бүтін сан. Бұл сәйкестік бағдарламаның дұрыстығының бір түрі және «const дұрыстығы» деп аталады. Бұл келісімшарт бойынша бағдарламалауға мүмкіндік береді, онда функциялар өздерінің типтік сипаттамасының бөлігі ретінде аргументтерін өзгертетінін немесе өзгертетінін, сондай-ақ қайтарылатын мәні өзгертілуі мүмкін екенін немесе еместін көрсетеді. Бұл типті тексеру негізінен көрсеткіштер мен сілтемелерге қатысты, бірақ қарапайым мәндер типтеріне (мысалы, бүтін сандарға) де, сондай-ақ күрделі дерек типтеріне немесе контейнерлер сияқты шаблонды типтерге де қатысты. Бұл факт `const` көбінесе алынып тасталуы мүмкін екендігімен жасырылады, себебі типке келтіру (жасырын типтік түрлендіру) және C тілінің мәні бойынша шақыру қағидасы (C++ және D тілдері мәні бойынша немесе сілтеме бойынша шақыруды қолдайды) осыған мүмкіндік береді.

Салдарлар

Тұрақтылық ұғымы компьютер жадында сақталған айнымалыны өзгертпеуге болмайтындығын білдірмейді. Керісінше, тұрақтылық – компиляция уақытында құрылатын және бағдарламашының не істеу керектігін көрсететін, бірақ олардың не істей алатынын міндетті түрде шектемейтін құрал. Дегенмен, алдын ала анықталған деректер (мысалы, `char const *` жол мәнділері) жағдайында C-дегі `const` көбінесе өзгертпейді.

Тұрақтыдан ажырату

Бағдарлама жұмыс іліп жатқанда тұрақтының мәні өзгермейді, бірақ const деп жарияланған объектінің мәні бағдарлама жұмыс іліп жатқанда өзгеріп қана қоймай, жаңа мән алуы мүмкін. Көп кездесетін мысал – кіріктірілген жүйелердегі, мысалы, цифрлық кіріс сияқты, тек оқуға арналған тіркелімдер. Цифрлық кіріс деректерінің тіркелімдері көбінесе const және volatile деп жарияланады. Бұл тіркелімдердің мазмұны бағдарламаның ешқандай әрекет жасамауының өзінде өзгеріп отыруы мүмкін (volatile), бірақ бағдарлама оларға жазуға тырысуы қате болады (const).

Басқа қолданыстар

Сонымен қатар, (статик емес) мүше функциясы const ретінде жариялануы мүмкін. Бұл жағдайда, мұндай функция ішіндегі this меңзері нысан түрінің const * типі болады, қарапайым нысан түрінің * типі емес. Бұл, осы объект үшін const емес функцияларды осындай функцияның ішінен шақыруға болмайды және мүше айнымалыларын өзгертуге де болмайды дегенді білдіреді. C++ тілінде мүше айнымалы mutable деп жариялануы мүмкін, бұл оған бұл шектеу қолданбайтынын көрсетеді. Кейбір жағдайларда бұл пайдалы болуы мүмкін, мысалы, кэштеу, сілтемелерді санау және деректерді синхрондау үшін. Мұндай жағдайларда объектінің логикалық мағынасы (күйі) өзгермейді, бірақ объект физикалық тұрғыдан тұрақты емес, себебі оның биттік өрнегі өзгеріп қалуы мүмкін.

Синтаксисі

C, C++ және D тілдерінде барлық дерек түрлері, пайдаланушы анықтаған түрлері де const деп жариялануы мүмкін, ал const дұрыстығы қағидасы бойынша барлық айнымалылар немесе объектілер өзгертілмейінше, осылай жариялануы тиіс. Const-ты белсенді пайдалану мәндерді "түсінуді, қадағалауды және талдауды жеңілдетеді", соның салдарынан кодты оқуға және түсінуге қолайлы етеді, сондай-ақ командалық жұмысты және кодты қолдауды жеңілдетеді, себебі ол мәннің арналуы туралы ақпаратты жеткізеді. Бұл компиляторға да, бағдарламашыға да кодты талдау кезінде көмектеседі. Бұдан өзге, оптимизациялайтын компиляторға тиімді код жасауға мүмкіндік береді.

Қарапайым дерек түрлері

Қарапайым көрсеткіш емес дерек түрлері үшін `const` модификаторын қолдану оңай. Тарихи себептерге байланысты, оны кейбір типтердің екі жағына да қоюға болады (мысалы, `const char foo = 'a';` және `char const foo = 'a';` бірдей). Кейбір жүйелерде `const` модификаторын екі рет қолдану (мысалы, `const char const` немесе `char const const`) ескерту шығарады, бірақ қателік тудырмайды.

Параметрлер мен айнымалылар

const функцияның параметрлеріне де, айнымалыларға да (статикалық немесе автоматты, оның ішінде жаһандық немесе жергілікті) жариялануы мүмкін. Түсіндіру қолданылуына қарай әртүрлі болады. Статикалық const айнымалы (жаһандық айнымалы немесе статикалық жергілікті айнымалы) тұрақты болып табылады және математикалық тұрақтылар сияқты деректер үшін қолданылуы мүмкін, мысалы, double const PI = 3.14159 – тізімі ұзағырақ немесе компиляция уақытының жалпы параметрлері. Автоматты const айнымалы (статикалық емес жергілікті айнымалы) бір рет мән тағайындалатынын білдіреді, бірақ әр жолы басқа мән қолданылуы мүмкін, мысалы, int const x_квадраты = x * x. Сілтеме арқылы берілген const параметрі сілтемеленген мәннің өзгертілмейтінін білдіреді – бұл келісімнің бір бөлігі, ал мән арқылы берілген const параметрі (немесе сілтеме арқылы берілген меңзердің өзі) интерфейске қосымша ештеңе қоспайды (мән көшірілген), бірақ функцияның ішінде параметрдің жергілікті көшірмесі өзгертілмейтінін көрсетеді (бір рет мән тағайындалады). Осы себепті, кейбірлер const параметрін тек сілтеме арқылы беру үшін қолдануды жақсы көреді, себебі ол келісімді өзгертеді, бірақ мән арқылы беру үшін емес, ол іске асыруды ашады.

Қиындықтар

Тұрақтылықты білдіру үшін типтік жүйені қолдану әртүрлі қиындықтар мен мәселелерге алып келеді, сондықтан оған сын айтылды және C, C++ және D тілдерінен басқа тар C отбасынан тысқары ешқайда қабылданбады. C және C++ тілдерінің күшті ықпалында болған Java және C# екеуі де const стиліндегі типтік белгілеуді нақты түрде қабылдамады, оның орнына идентификаторға қатысты түйін сөздер арқылы тұрақтылықты көрсетеді (Java-да final, ал C#-да const және readonly). Тіпті C және C++ тілдерінің ішінде де const қолданылуы айқын ерекшеленеді, кейбір жобалар мен ұйымдар оны тұрақты түрде қолданады, ал басқалары одан қашып жүреді.

Тарих

const 1981 жылы Бьярн Строструп C with Classes бағдарламасында, C++ бағдарламасының алдындағы нұсқасында енгізді және бастапқыда readonly деп аталды. Струструп мотивация туралы былай деп жазады: 1987 жылдың желтоқсанындағы X3J11 комитетінің мәжілісінде noalias деген тағы бір модификатор ұсынылды, бірақ қабылданбады; оның мақсаты ақырында C99 стандартындағы restrict кілт сөзімен іске асырылды. Ричи бұл қосымшаларды қолдамады, олар "пайдасы аз" дей отырып, бірақ оларды стандарттан алып тастауға қарсы шықпады. D кейіннен C++-тан const-ты мұралады, онда ол типтік конструктор (типтік модификатор емес) ретінде танылады және осыған ұқсас қолдану жағдайларын басқару үшін immutable және inout деген тағы екі типтік конструкторды қосты.

Басқа тілдер

Басқа тілдер C/C++ сияқты тұрақтылықтың типтің бір бөлігі болуын қабылдамайды, бірақ олардың көпшілігінде сырттай ұқсас конструкциялар бар және const кілт сөзін қолдануға болады. Әдетте, бұл тек тұрақтыларға (тұрақты объектілерге) қатысты қолданылады. C# кілт сөзі const-қа ие, бірақ оның мағынасы түбегейлі түрлендірілген және қарапайым: ол компиляция уақытындағы тұрақтыны білдіреді және типтің бөлігі емес. Nim-дегі const кілт сөзі C#-қа ұқсас: ол типтің бір бөлігін құрудың орнына компиляция уақытындағы тұрақтыны жариялайды. Алайда, Nim-де кез келген өрнекті, компиляция уақытында есептелуі мүмкін болса, тұрақты деп жариялауға болады. C#-та тек C# құрастырған типтерді ғана const деп жариялауға болады; пайдаланушы анықтаған типтер, соның ішінде класс, құрылымдар және массивтер const бола алмайды. Java-да const жоқ, оның орнына final бар, оны жергілікті "айнымалы" жариялауларда қолдануға болады және ол типке емес, идентификаторға қатысты. Ол объект мүшелері үшін басқа объектіге бағытталған қолданысқа ие, осы атаудың шығу тегі де осыдан. Java тілінің сипаттамасы const-ты резервтелген кілт сөз деп санайды, яғни оны айнымалы идентификаторы ретінде қолдануға болмайды, бірақ оған ешқандай семантика тағайындалмайды: ол резервтелген сөз (анықтамаларда қолданылмайды), бірақ кілт сөз емес (оның ерекше мағынасы жоқ). Кілт сөзді резервтеу Java тілін C++ стиліндегі const әдістерін және const типіне сілтеме жасауды қосу арқылы кеңейтуге мүмкіндік беру үшін жасалған деп есептеледі. Java Community Process-те const дұрыстығын енгізу туралы ұсыныс бар, бірақ ол 2005 жылы артқа қарай үйлесімділікпен жүзеге асыру мүмкін емес деген себеппен жабылды. Қазіргі Ada 83 дербес тұрақты объект және const кілт сөзіне ие болды, кіріс параметрлері мен цикл параметрлері тұжырымдама бойынша тұрақты болды. Мұнда тұрақты – типтің емес, объектінің қасиеті. JavaScript-те const жариялануы бар, ол қайта тағайындауға немесе қайта жариялауға болмайтын блокқа арналған айнымалыны анықтайды. Ол қайта анықтауға болмайтын айнымалыға тек оқуға арналған сілтемені анықтайды, бірақ кейбір жағдайларда айнымалының мәні өзгеруі мүмкін, мысалы, егер айнымалы объектіге сілтеме жасаса және оның қасиеті өзгертілсе.