08 / 90

C++ Constants

C++ konstantalari

const kalit so'zi (o'zgarmas ma'noni anglatadi) o'zgaruvchining qiymatini dasturning istalgan joyida ataylab yoki tasodifan o'zgartirib bo'lmasligini ko'rsatish uchun ishlatiladi. Masalan,

example.cpp
// PI ni doimiyga aylantiradi
const double PI = 3.14;

[!NOTE] Konstantalarni nomlashning standart qoidasi shundan iboratki, ularning barchasi katta harflar bilan yozilishi kerak. Masalan, const int MAGIC_NUMBER = 42;

const o'zgaruvchilarni yarating

const o'zgaruvchisi deklaratsiya paytida ishga tushirilishi kerak va keyin uni o'zgartirib bo'lmaydi.

example.cpp
// yaroqsiz, chunki PI ishga tushirilmagan
const double PI;

const o‘zgaruvchisi PI ishga tushirilmaganligi sababli bu yerda xatoga yo‘l qo‘ydik.

Buning o'rniga, biz const o'zgaruvchilarni quyidagi tarzda ishga tushirish orqali yaratishimiz kerak:

example.cpp
// const ni qiymat bilan ishga tushiring
const double PI = 3.14;

1-misol: C++ const

example.cpp
#include <iostream>
using namespace std;

int main() {
    
    // const PI ni ishga tushiring
    const double PI = 3.14;
    
    int radius = 4;

    // hisoblashda const dan foydalaning
    double area = PI * radius * radius;
    
    cout << "Area of circle with radius " << radius << " is: " << area;

    return 0;
}

Chiqish

kod
Area of circle with radius 4 is: 50.24

Yuqoridagi misolda biz doimiy o'zgaruvchi PIni ishga tushirdik.

example.cpp
const double PI = 3.14;

Keyin biz aylananing maydonini hisoblash uchun ushbu doimiy o'zgaruvchidan foydalandik:

example.cpp
double area = PI * radius * radius;

Const havolalar

Shuningdek, biz const kalit so'zidan foydalanib murojaat qilishimiz mumkin. Har xil xatti-harakatlarga ega bo'lgan bunday murojaatlarning har xil turlari mavjud. Bular

Malumot turi Ta'rif Doimiy o'zgaruvchiga doimiy havola O'zgaruvchi ham, havola ham doimiydir. Doimiy bo'lmagan o'zgaruvchiga doimiy havola O'zgaruvchi doimiy emas, lekin havola doimiy.

Const o'zgaruvchisiga Const havolasi

C++ tilida biz mos yozuvlar o‘zgaruvchisi yordamida const o‘zgaruvchisiga const havolasini yaratishimiz mumkin. Masalan,

example.cpp
#include <iostream>
using namespace std;

int main() {

    // doimiy PI ni ishga tushiring
    const double PI = 3.14;
  
    // PIga faqat o'qish uchun havola yaratish
    const double &PI_REF = PI;
  
    cout << "PI: " << PI;
    cout << "\nPI_REF: " << PI_REF;
  
    return 0;
}

Chiqish

kod
PI: 3.14
PI_REF: 3.14

Yuqoridagi misolda biz doimiy yoki doimiy havolaga doimiy havola yaratdik.

Shunday qilib, PI_REF qiymatini o'zgartirishga harakat qilsak, xatoga yo'l qo'yamiz.

example.cpp
// xato: "PI_REF" faqat o'qish uchun havolani tayinlash
PI_REF = 90;

Tez-tez so'raladigan savol Ha, doimiy havola doimiy bo'lmagan o'zgaruvchiga murojaat qilishi mumkin. Biroq, biz ushbu havola yordamida qiymatni o'zgartira olmaymiz. Masalan, #include <iostream> using namespace std; int main() { int num = 10; // constant reference to a non constant variable const int &NUM_REF = num; cout << NUM_REF; return 0; } 10 chiqishi Yuqoridagi misolda biz doimiy bo'lmagan o'zgaruvchiga doimiy havola yaratdik. Natijada, biz NUM_REF mos yozuvlar o'zgaruvchisi yordamida num qiymatini o'zgartira olmaymiz. // xato: faqat oʻqish uchun moʻljallangan “NUM_REF” maʼlumotnomasini tayinlash NUM_REF = 67;

Doimiy ma'lumotnoma sifatida o'tish

O'tkazilgan argument funksiya tanasi tomonidan o'zgartirilmasligini ta'minlash uchun biz doimiy parametrdan foydalanishimiz mumkin.

Masalan, biz o'tkazgan vektor quyidagi kod yordamida o'zgartirilmasligiga ishonch hosil qilishimiz mumkin:

example.cpp
int sum(const vector<int> nums) {
    // funksiya tanasi
}

Yuqoridagi koddagi const kalit so'zi raqamlarni o'zgartirib bo'lmasligini kafolatlagan bo'lsa-da, u raqamlarning mahalliy nusxasini yaratadi, bu esa xotirani talab qiladi.

Buni hal qilishning eng yaxshi usuli bu quyidagi kod yordamida doimiy havola sifatida o'tishdir:

example.cpp
int sum(const vector<int> &nums) {
    // funksiya tanasi
}

Bu yerda &nums havola bo‘lib, const kalit so‘zi uning doimiy ekanligini bildiradi.

3-misol: Doimiy ma'lumotnoma sifatida o'tish

example.cpp
#include <iostream>
#include <vector>
using namespace std;

// argument sifatida const havolasini oling
int sum(const vector<int> &nums) {
    int total = 0;

    for(auto num: nums){
        total += num;
    }

    return total;
}

int main() {

    vector<int> nums = {1, 2, 3, 4, 5};

    cout << "Sum: " << sum(nums);

    return 0;
}

Chiqish

kod
Sum: 15

Yuqoridagi misolda biz doimiy havola sifatida nums vektorini o'tkazdik:

example.cpp
int sum(const vector<int> &nums) {
    // kod
}

Bu erda nums vektorining mahalliy nusxasini yaratish o'rniga, biz o'zgartirib bo'lmaydigan havolani uzatmoqdamiz. Bu tezroq va bo'sh joyni tejaydi.

Const va Pointer

Ma'lumotnomalar singari, biz const kalit so'zidan foydalanib, har xil turdagi ko'rsatkichlarni yaratishimiz mumkin. Bular:

Ko'rsatkich turi Ta'rif Const uchun ko'rsatkichlar Ko'rsatkich doimiy emas, lekin ko'rsatilayotgan qiymat doimiydir. Const Pointer Ko'rsatkich doimiy, lekin ko'rsatilayotgan qiymat doimiy emas. Const Const ko'rsatkichi Ko'rsatkich ham, ko'rsatilayotgan qiymat ham doimiydir.

Const uchun ko'rsatkichlar

Const ga ko'rsatkich doimiy o'zgaruvchiga ishora qiluvchi pointer o'zgaruvchisidir. Bu ko'rsatkichlar

  • ko'rsatkich ko'rsatayotgan manzilni o'zgartirishga ruxsat bering,
  • o'sha doimiy o'zgaruvchilarda saqlangan qiymatni o'zgartirishga ruxsat bermang.

Masalan,

example.cpp
#include <iostream>
using namespace std;

int main() {

    // doimiy TOTAL_MONTHSni ishga tushiring
    const int TOTAL_MONTHS = 12;
 
    // MONTHS_PTR int const uchun ko'rsatgichdir
    const int *MONTHS_PTR = &TOTAL_MONTHS;
  
    cout << "TOTAL_MONTHS: " << TOTAL_MONTHS << endl;
    cout << "*MONTHS_PTR: " << *MONTHS_PTR << endl;

    // boshqa int konstantasini yarating
    const int HALF_MONTHS = 6;

    // MONTHS_PTR endi HALF_MONTHSni ko‘rsatmoqda
    MONTHS_PTR = &HALF_MONTHS;

    cout << endl;
  
    cout << "HALF_MONTHS: " << HALF_MONTHS << endl;
    cout << "*MONTHS_PTR: " << *MONTHS_PTR;

    return 0;
}

Chiqish

kod
TOTAL_MONTHS: 12
*MONTHS_PTR: 12

HALF_MONTHS: 6
*MONTHS_PTR: 6

Yuqoridagi misolda biz TOTAL_MONTHS butun son konstantasini yaratdik. Keyin, biz MONTHS_PTR deb nomlangan doimiyga ko'rsatkich yaratdik.

example.cpp
// ball to const int TOTAL_MONTHS
const int *MONTHS_PTR = &TOTAL_MONTHS;

MONTHS_PTR da qiymatni o‘zgartirmoqchi bo‘lsak, xatoga yo‘l qo‘yamiz.

example.cpp
// xato: "* TOTAL_MONTHS_PTR" faqat o'qish uchun joyni belgilash
*TOTAL_MONTHS_PTR = 10;

Buning sababi, TOTAL_MONTHS qiymati doimiy va uni o‘zgartirib bo‘lmaydi.

Biroq, biz MONTHS_PTR tomonidan ko'rsatilgan manzilni xatosiz boshqa o'zgaruvchiga ishora qilish uchun o'zgartirishimiz mumkin.

example.cpp
const int HALF_MONTHS = 6;
MONTHS_PTR = &HALF_MONTHS;

Const Pointer

Const ko'rsatkichi pointer bo'lib, unda biz ko'rsatkich ko'rsatgan qiymatni o'zgartirishimiz mumkin, lekin u ko'rsatgan o'zgaruvchini o'zgartira olmaymiz. Masalan,

example.cpp
#include <iostream>
using namespace std;

int main() {
    
    string country1 = "Nepal";
    string country2 = "USA";
  
    cout << "Initially, country1: " << country1 << endl;
  
    // PTR1 mamlakat1 uchun konst ko'rsatkichidir
    string *const PTR1 = &country1;
  
    // PTR1 yordamida mamlakat1 qiymatini o'zgartiring
    *PTR1 = country2;
  
    cout << "Finally, country1: " << country1;
  
    return 0;
}

Chiqish

kod
Initially, country1: Nepal
Finally, country1: USA

Yuqoridagi misolda biz const ko'rsatkichini yaratdik.

example.cpp
// PTR1 - bu satrning konst ko'rsatkichi
string *const PTR1 = &country1;

Dastlab mamlakat1 qiymati Nepal dir. Keyin, biz PTR1 yordamida mamlakat1 qiymatini o'zgartirdik:

example.cpp
// PTR1 tomonidan ko'rsatilgan o'zgaruvchining qiymatini o'zgartiring
*PTR1 = country2;

Shunday qilib, country1 ning yangi qiymati USA ga aylanadi.

Ammo PTR1 tomonidan ko'rsatilgan o'zgaruvchini mamlakat1 dan mamlakat2 ga o'zgartirmoqchi bo'lsak, xatoga duch kelamiz:

example.cpp
// xato: "PTR1" faqat o'qiladigan o'zgaruvchini tayinlash
PTR1 = &country2;

Const ko'rsatkichi Const

Const ko'rsatkichi - bu ko'rsatkich bo'lib, u orqali biz na u ko'rsatadigan o'zgaruvchini, na uning qiymatini o'zgartira olmaymiz. Masalan,

example.cpp
#include <iostream>
using namespace std;

int main() {
    
    // const o'zgaruvchisini yarating
    const string COUNTRY1 = "Nepal";
    
    // const uchun const ko'rsatkichini yarating
    const string *const PTR = &COUNTRY1;

    cout << *PTR;
  
    return 0;
}

Chiqish

kod
Nepal

Tez-tez so'raladigan savol Const ko'rsatkichi ko'rsatkich orqali o'zgartirilmasligi kerak bo'lgan qiymatga ishora qiluvchi ko'rsatgichga ishora qiladi. Boshqa tomondan, const ko'rsatkichi ishga tushirilgandan keyin boshqa manzilga ishora qila olmaydigan ko'rsatgichdir. Masalan, 1. ko'rsatkich const: const int* ptr_to_const = &value; // Error: Can't modify the value pointed to *ptr_to_const = 20; // OK: The pointer can point to another address ptr_to_const = &another_value; 2. const pointer: int* const const_ptr = &value; // OK: The value pointed to can be changed *const_ptr = 30; // Error: Can't change the address the pointer is pointing to const_ptr = &another_value;

Const ifodasi

Doimiy ifodalar C++ 11 da kiritilgan. Ular quyidagi ifodalardir:

  • qiymat o'zgarmaydi,
  • va kompilyatsiya vaqtida baholanishi mumkin.

Biz ularni C++ da ishlatishni istashimizning sababi hisob-kitoblarni ish vaqtida bir necha marta bajarmaslikdir.

Doimiy ifodalarni yaratish uchun constexpr kalit so'zidan foydalanamiz. Masalan,

example.cpp
// funksiyani constexpr deb e'lon qilish
constexpr int add_numbers(int a, int b) {...}

// o'zgaruvchini constexpr deb e'lon qilish
constexpr int sum = add_numbers(660, 6);

[!NOTE] constexpr sifatida e'lon qilinmagan funksiyalarni chaqirish uchun constexpr o'zgaruvchilaridan foydalana olmaymiz:

4-misol: C++ Const ifodasi

example.cpp
#include <iostream>
using namespace std;

// constexpr funksiyasi
// n-fibonachchi raqamini qaytaradi
constexpr int fib(int n) {

    // n ni qaytaradi, agar n <= 1 bo'lsa
    // aks holda, rekursiv ravishda fib(n - 1) + fib(n - 2) ni chaqiradi.
    return n <= 1 ? n: fib(n - 1) + fib(n - 2);   
}

int main() {

    // saqlaydigan ikkita constexpr o'zgaruvchisi
    // constexpr funksiyasining qaytish qiymatlari
    constexpr int fibonacci_five = fib(5);
    constexpr int fibonacci_ten = fib(10);

    cout << "fib(5) : "<< fibonacci_five << endl;
    cout << "fib(10) : "<< fibonacci_ten;

    return 0;
}

Chiqish

kod
fib(5) : 5
fib(10) : 55

Yuqoridagi misolda biz n-fibonachchi sonini baholash uchun doimiy ifodani (funksiya shaklida) yaratdik.

example.cpp
constexpr int fib(int n) {    
    return n <= 1 ? n: fib(n - 1) + fib(n - 2);   
}

E'tibor bering, biz constexpr kalit so'zini qaytarish turidan oldin qo'shdik, bu esa kompilyatorga funksiya kompilyatsiya vaqtida baholanishi kerakligini aytadi.

Keyin ikkita constexpr o'zgaruvchisi yordamida 5 va 10-fibonachchi raqamlarini hisoblaymiz:

example.cpp
constexpr int fibonacci_five = fib(5);
constexpr int fibonacci_ten = fib(10);

Endi biz oddiy funksiya chaqiruvini bajarayotganimizga e'tibor bering. Faqatgina farq shundaki, hisoblash kompilyatsiya vaqtida amalga oshiriladi.

[!NOTE] // funksiya constexpr int fib(int n) {...} // xato: 'constexpr' bo'lmagan funksiyaga qo'ng'iroq qilish 'int fib(int)' constexpr int fibonacci_five = fib(5); Biroq, biz constexpr funksiyalarini chaqirish uchun constexpr bo'lmagan o'zgaruvchilardan foydalanishimiz mumkin: constexpr int fib(int n) {...} // valid code int fibonacci_five = fib(5);

Const a'zosi funksiyalari

Const a'zo funksiyalari ob'ektning ma'lumotlar a'zolari o'zgarmasligini ta'minlaydi. Biz bunday funksiyalarni quyidagi sintaksis bilan yaratamiz:

example.cpp
return_type function_name() const {
    // funksiya tanasi
}

Const a'zo funksiyalarining xossalari

  • Biz const a'zo funksiyasi ichidagi a'zo o'zgaruvchilar qiymatlarini o'zgartira olmaymiz.
  • Biz faqat doimiy ob'ektdan const a'zo funksiyalarini chaqira olamiz.

5-misol: Const a'zo funksiyalari

example.cpp
#include <iostream>
using namespace  std;

class Rectangle {
private:
    int breadth, length;

public:
    Rectangle(int length, int breadth){
        this->breadth = breadth;
        this->length = length;
    }

     // doimiy a'zo funksiyasi
    int get_area() const {
        return length * breadth;
    }

    // doimiy bo'lmagan a'zo funksiyasi
    int get_perimeter() {
        return 2 * (length + breadth);
    }
};

int main() {

    // const Rectangle obyektini yarating
    const Rectangle RECT = Rectangle(7, 6);

    // const a'zo funksiyasini chaqiring
    cout << "Area: " << RECT.get_area() << endl;

    return 0;
}

Chiqish

kod
Area: 42

Yuqoridagi misolda biz quyidagi a'zo funksiyalari bilan Rectangle sinfini yaratdik:

  • get_area() - a constant member function
  • get_perimeter()- a normal member function

main() da biz RECT nomli doimiy ob'ektni yaratdik:

example.cpp
// const Rectangle obyektini yarating
const Rectangle RECT = Rectangle(7, 6);

Keyin, biz RECT doimiy ob'ekti yordamida get_area() const a'zo funksiyasini chaqirdik:

example.cpp
// 
RECT.get_area();

Doimiy bo'lmagan a'zo funksiyalarni chaqirish

Biroq, agar biz get_perimeter() const bo'lmagan a'zo funksiyasini chaqirishga harakat qilsak, xatoga duch kelamiz:

example.cpp
// xato
RECT.get_perimeter();

Buning sababi shundaki, doimiy ob'ekt doimiy bo'lmagan a'zo funksiyani chaqira olmaydi.

Biroq, doimiy bo'lmagan ob'ekt ham doimiy, ham doimiy bo'lmagan a'zo funksiyalarni chaqirishi mumkin.

Buning sababi oddiy: biz ma'lumotlar a'zolari o'zgartirilmasligi uchun doimiy ob'ekt yaratamiz. Lekin doimiy bo'lmagan a'zo funksiyalari ma'lumotlar a'zolarini o'zgartirish imkoniyatiga ega.

Shunday qilib, doimiy ob'ektning maqsadi doimiy bo'lmagan a'zo funksiyasining maqsadiga zid keladi, shuning uchun biz funksiya chaqiruvini bajara olmaymiz.