33 / 90

C++ Pass by Reference with Pointers

C++ funksiyaga ko'rsatkich va havola uzatish

C++ Functions qo'llanmasida biz funksiyaga argumentlarni uzatish haqida bilib oldik. Amaldagi bu usul pass by qiymat deb ataladi, chunki haqiqiy qiymat uzatiladi.

Biroq, argumentlarni o'tkazishning yana bir yo'li bor - havola orqali o'tish.

Malumot orqali o'tish - bu funksiyaga ularning qiymatlari emas, balki haqiqiy parametrlarning havolalari uzatiladigan funksiyalarda argumentlarni o'tkazish usuli.

Masalan,

example.cpp
// qiymatni parametr sifatida qabul qiladigan funksiya

void func1(int num_val) {
    // kod
}

// parametr sifatida mos yozuvlarni qabul qiladigan funksiya
// parametrdan oldin & ga e'tibor bering
void func2(int& num_ref) {
    // kod
}

int main() {
    int num = 5;

    // qiymat bo'yicha o'tish
    func1(num);

    // ma'lumotnoma orqali o'ting
    func2(num);

    return 0;
}

void func2(int& num_ref) da & ga e'tibor bering. Bu bizning parametrimiz sifatida variable havolasidan foydalanayotganimizni bildiradi.

Shunday qilib, biz main() da func2() funksiyasini num o'zgaruvchisini argument sifatida berish orqali chaqirganimizda, biz aslida 5 qiymati o'rniga num o'zgaruvchisiga havolani uzatamiz.

Misol: Malumot bo'yicha o'tish

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

// qiymatlarni almashtirish uchun funksiya ta'rifi
void swap(int& n1, int& n2) {
    int temp;
    temp = n1;
    n1 = n2;
    n2 = temp;
}

int main() {

    // o'zgaruvchilarni ishga tushirish
    int a = 1, b = 2;

    cout << "Before swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    // raqamlarni almashtirish uchun qo'ng'iroq funksiyasi
    swap(a, b);

    cout << "\nAfter swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    return 0;
}

Chiqish

kod
Before swapping
a = 1
b = 2

After swapping
a = 2
b = 1

Ushbu dasturda biz a va b o'zgaruvchilarni swap() funksiyasiga o'tkazdik. Funksiya ta'rifiga e'tibor bering,

example.cpp
void swap(int& n1, int& n2)

Bu erda funksiya o'z parametrlari sifatida havolalarni qabul qilishini bildirish uchun & dan foydalandik.

Shunday qilib, kompilyator haqiqiy qiymatlar o'rniga o'zgaruvchilarning havolasi funksiya parametrlariga o'tkazilishini aniqlay oladi.

swap() funksiyasida n1 va n2 funksiya parametrlari mos ravishda a va b o‘zgaruvchilari bilan bir xil qiymatga ishora qiladi. Shuning uchun almashtirish haqiqiy qiymat bo'yicha amalga oshiriladi.

Const Reference orqali o'ting

Agar o'zgaruvchilar qiymatlarini o'zgartirish kerak bo'lmasa, biz ularni const havolalari sifatida o'tkazishimiz mumkin.

Keling, bir misolni ko'rib chiqaylik.

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

// ikkita raqamni qo'shish funksiyasi
// const havolalaridan foydalanish
int add(const int& num1, const int& num2) {
    return num1 + num2;
}

int main() {
    int number1, number2;

    // kiritish
    cout << "Enter the first number: ";
    cin >> number1;

    cout << "Enter the second number: ";
    cin >> number2;

    // qo'ng'iroq qilish funksiyasi
    int sum = add(number1, number2);

    // natijani ko'rsatish
    cout << "The sum of " << number1 << " and " << number2 << " is " << sum << endl;

    return 0;
}

Chiqish

kod
Enter the first number: 1
Enter the second number: 2
The sum of 1 and 2 is 3

Bu erda biz const havolalari yordamida qiymatlarni uzatish uchun const kalit so'zidan foydalandik.

const havolalaridan foydalanish funksiya ichidagi qiymatlarni o'zgartirishni oldini oladi. Masalan, ikkita raqamni almashtirish uchun const havolalaridan foydalanishga harakat qilaylik.

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

// qiymatlarni almashtirish uchun funksiya ta'rifi
// const havolalaridan foydalanish
void swap(const int& n1,const int& n2) {
    int temp;
    temp = n1;
    n1 = n2;
    n2 = temp;
}

int main() {

    // o'zgaruvchilarni ishga tushirish
    int a = 1, b = 2;

    cout << "Before swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    // raqamlarni almashtirish uchun qo'ng'iroq funksiyasi
    swap(a, b);

    cout << "\nAfter swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    return 0;
}

Chiqish

kod
ERROR!
/tmp/RXT9OkJpWq.cpp: In function 'void swap(const int&, const int&)':
/tmp/RXT9OkJpWq.cpp:9:8: error: assignment of read-only reference 'n1'
    9 |     n1 = n2;
      |     ~~~^~~~
/tmp/RXT9OkJpWq.cpp:10:8: error: assignment of read-only reference 'n2'
   10 |     n2 = temp;
      |     ~~~^~~~~~

const havolalari yordamida uzatilgan oʻzgaruvchilar qiymatlarini oʻzgartirishga urinib koʻrganimiz uchun bu yerda xatoga yoʻl qoʻydik.

[!NOTE] const havolalaridan foydalanib, biz kodimiz ustidan ko'proq nazoratga ega bo'lamiz, chunki biz qaysi funksiyalar o'zgaruvchilar qiymatlarini o'zgartirishi va o'zgartira olmasligini aniq aniqlashimiz mumkin. Bu kod xavfsizligini oshiradi va disk raskadrovkani osonlashtiradi.

Ko'rsatkichlar bo'ylab o'tish (ruhsiz)

Yuqoridagi vazifani ko'rsatkichlar yordamida bajarish mumkin. Ko'rsatkichlar haqida bilish uchun C++ Pointers ga tashrif buyuring.

Keling, bir misolni ko'rib chiqaylik.

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

// funksiya prototipi parametr sifatida ko'rsatkichlar bilan
void swap(int*, int*);

int main() {

    // o'zgaruvchilarni ishga tushirish
    int a = 1, b = 2;

    cout << "Before swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    // o'zgaruvchan manzillarni o'tkazish orqali chaqiruv funksiyasi
    swap(&a, &b);

    cout << "\nAfter swapping" << endl;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}

// raqamlarni almashtirish uchun funksiya ta'rifi
void swap(int* n1, int* n2) {
    int temp;
    temp = *n1;
    *n1 = *n2;
    *n2 = temp;
}

Chiqish

kod
Before swapping
a = 1
b = 2

After swapping
a = 2
b = 1

Bu erda biz oldingi misoldagi kabi chiqishni ko'rishimiz mumkin. Chiziqqa e'tibor bering,

example.cpp
// &a - a manzili
// &b - b manzili
swap(&a, &b);

Bu erda o'zgaruvchining manzili o'zgaruvchiga emas, balki funksiya chaqiruvi vaqtida uzatiladi.

Qiymat o'rniga manzil uzatilganligi sababli, ushbu manzilda saqlangan qiymatga kirish uchun * yo'qotish operatoridan foydalanish kerak.

example.cpp
temp = *n1;
*n1 = *n2;
*n2 = temp;

*n1 va *n2 mos ravishda n1 va n2 manzillarida saqlangan qiymatni beradi.

n1 va n2 a va b manzillarini o'z ichiga olganligi sababli, *n1 uchun hamma narsa bajariladi va *n2 a va b ning haqiqiy qiymatlarini o'zgartiradi.

Demak, main() funksiyasida a va b qiymatlarini chop etganimizda qiymatlar o'zgartiriladi.

[!NOTE] Ko'rsatkichlar o'rniga havolalardan foydalanish odatda osonroq va xatoga yo'l qo'ymaydi, chunki u to'g'ridan-to'g'ri ko'rsatkich operatsiyalarini o'z ichiga olmaydi. Ko'rsatkichlar faqat ko'rsatkichlar zarur bo'lgan kontekstlarda yoki C kutubxonalari bilan o'zaro aloqada bo'lganda argumentlarni uzatish uchun ishlatilishi kerak.