Xem thêm

Bài 33. Tham chiếu và tham trị trong C++

Huy Erick
Chào mừng các bạn đến với bài học mới của Lập trình không khó! Hôm nay chúng ta sẽ tìm hiểu về hai khái niệm quan trọng trong ngôn ngữ lập trình C++, đó là...

Chào mừng các bạn đến với bài học mới của Lập trình không khó! Hôm nay chúng ta sẽ tìm hiểu về hai khái niệm quan trọng trong ngôn ngữ lập trình C++, đó là "tham chiếu" và "tham trị".

Tham chiếu và tham trị: Định nghĩa

"Tham chiếu" và "tham trị" là hai cách truyền tham số vào hàm khác nhau. Tùy vào mục đích sử dụng mà chúng ta sẽ chọn cách truyền tham số phù hợp. Hôm nay, chúng ta sẽ cùng nhau làm rõ hai khái niệm này qua các bài tập thực hành.

Lưu ý: Các khái niệm "tham chiếu" và "tham trị" được sử dụng trong ngôn ngữ C++. Đối với ngôn ngữ C, bạn cần đọc về "tham chiếu" sau khi đã nắm vững về con trỏ.

Hình ảnh mô phỏng tham chiếu và tham trị trong C++ Hình ảnh mô phỏng tham chiếu (pass by reference) và tham trị (pass by value) trong C++. Trong đó cup là một biến được truyền vào lời gọi hàm fillCup(). Khi truyền theo tham chiếu thì hàm có khả năng thay đổi giá trị của tham số của hàm; Còn truyền theo tham trị thì hàm không thể thay đổi giá trị của tham số. Nguồn ảnh: mathwarehouse

Video hướng dẫn tham chiếu và tham trị

Trước khi đi vào chi tiết, hãy xem video dưới đây để hiểu rõ hơn về cách sử dụng tham chiếu và tham trị trong C++.

Source code trong video hướng dẫn về tham trị và tham chiếu:

/* truyền tham trị(giá trị): pass by value
   truyền tham chiếu: pass by reference */
/* Viết hàm hoán vị 2 số */
#include 
void Swap(int &a, int &b){
   int tmp = a;
   a = b;
   b = tmp;
}
void increment(int &n){
   n++;
}
int main(){
   int first, second;
   printf("Nhập first = ");
   scanf("%d", &first);
   printf("Nhập second = ");
   scanf("%d", &second);
   printf("first = %d, second = %d", first, second);
   increment(first);
   increment(second);
   Swap(first, second);
   printf("first = %d, second = %d", first, second);
}

Kết quả chạy chương trình:

Nhập first = 4
Nhập second = 5
first = 4, second = 5
first = 5, second = 4

Làm rõ tham trị và tham chiếu

Để hiểu rõ hơn về hai khái niệm "tham trị" và "tham chiếu", chúng ta hãy đọc kết hợp cả phần tham chiếu và tham trị. Điều này sẽ giúp chúng ta phân biệt dễ dàng hai khái niệm này, cũng như cách sử dụng và khi nào cần sử dụng chúng.

Tham chiếu là gì?

  • Khai báo hàm sử dụng tham số dưới dạng tham chiếu bằng cách thêm dấu & vào trước tham số đó. Ví dụ: int f(int &x).
  • Khi một biến a được truyền vào lời gọi hàm f(int &x) làm tham số dưới dạng tham chiếu, thì biến x của hàm f(int &x) và biến a thực chất là một. Do đó, nếu hàm thay đổi giá trị của x trong hàm f(int &x) này thì đồng nghĩa tại nơi gọi hàm, biến a cũng bị thay đổi theo.
  • Nếu tham số là mảng hoặc chuỗi, thì tham số này được truyền theo tham chiếu.

Tham trị là gì?

  • Chúng ta thường sử dụng cách truyền tham số theo tham trị trong hầu hết các bài học trước. Ví dụ: int f(int x).
  • Khi một biến a được truyền vào lời gọi hàm f(int x) làm tham số dưới dạng tham trị, thì biến x của hàm f(int x) và biến a là hai biến độc lập. Bởi vì khi tham số của hàm f(int x) là tham trị, hàm này sẽ tạo ra một biến mới và sao chép giá trị của a vào. Do đó, nếu hàm thay đổi giá trị của x trong hàm f(int x) này thì không tác động gì tới giá trị của biến a.

Ví dụ về tham chiếu và tham trị trong C++

Ở ví dụ này, chúng ta sẽ cùng nhau viết một hàm kiểu void nhận vào một biến số nguyên và thân hàm có nhiệm vụ tăng giá trị tham số đó lên một đơn vị.

Khi hàm của chúng ta nhận tham số dưới dạng tham trị:

#include 
void PassByValue(int n){
   n++; // Tăng n lên một đơn vị
   printf("Địa chỉ của n: %d", &n); // Lấy địa chỉ của biến
}
int main(){
   int value;
   printf("Nhập value = ");
   scanf("%d", &value);
   printf("Địa chỉ của n: %d", &value); // Lấy địa chỉ của biến
   printf("Trước khi gọi hàm value = %d", value);
   PassByValue(value);
   printf("Sau khi gọi hàm value = %d", value);
}

Kết quả chạy chương trình:

Nhập value = 5
Địa chỉ của n: 6487580
Trước khi gọi hàm value = 5
Địa chỉ của n: 6487536
Sau khi gọi hàm value = 5

Như bạn thấy, khi hàm được truyền theo tham trị thì:

  • Giá trị của biến value trong hàm main không bị thay đổi.
  • Địa chỉ của value trong hàm main và địa chỉ của n trong hàm PassByValue là khác nhau.

Khi hàm của chúng ta nhận tham số dưới dạng tham chiếu:

#include 
void PassByReference(int &n){ // Truyền theo tham chiếu
   n++; // Tăng n lên một đơn vị
   printf("Địa chỉ của n: %d", &n); // Lấy địa chỉ của biến
}
int main(){
   int value;
   printf("Nhập value = ");
   scanf("%d", &value);
   printf("Địa chỉ của n: %d", &value); // Lấy địa chỉ của biến
   printf("Trước khi gọi hàm value = %d", value);
   PassByReference(value);
   printf("Sau khi gọi hàm value = %d", value);
}

Kết quả chạy chương trình:

Nhập value = 5
Địa chỉ của n: 6487580
Trước khi gọi hàm value = 5
Địa chỉ của n: 6487580
Sau khi gọi hàm value = 6

Như bạn thấy, khi hàm nhận tham số là tham chiếu thì:

  • Giá trị của biến value trong hàm main bị thay đổi đúng theo cách biến n bị thay đổi trong hàm PassByReference.
  • Địa chỉ của value trong hàm main và địa chỉ của n trong hàm PassByReference là giống nhau, nghĩa là chúng cùng là một biến.

Kết luận về tham chiếu và tham trị trong C++

Qua bài học và các ví dụ mình đã trình bày ở trên, mình có một số tóm tắt về tham chiếu và tham trị như sau:

  • Dùng tham trị khi bạn không muốn giá trị của biến bị thay đổi.
  • Dùng tham chiếu khi bạn muốn hàm thay đổi giá trị biến của bạn.
  • Dùng tham chiếu sẽ tiết kiệm bộ nhớ hơn, vì nó không phải tạo ra một bản sao.
  • Nếu bạn dùng tham chiếu, bạn cũng không muốn hàm thay đổi giá trị của bạn thì bạn cần thêm từ khóa const vào tham số đó. Ví dụ: int f(const int &x).
  • Nếu tham số là mảng, truyền theo tham chiếu. Chúng ta sẽ tìm hiểu thêm trong chương sau.

Hy vọng rằng bài học này đã giúp bạn hiểu rõ hơn về tham chiếu và tham trị trong ngôn ngữ lập trình C++. Hãy thực hành thật nhiều để làm quen với cách sử dụng hai khái niệm này.

1