Tham Chiếu và Tham Trị là cách truyền tham số mà chúng ta thường gặp trong các bài toán hàm hoặc mảng trong C/C++, nó cũng là một vấn đề khá đau đầu nếu như chúng ta không hiểu. Nhưng bạn không phải lo, đọc kỹ bài viết này, tôi tin chắc rằng bạn sẽ hiểu nó ngay đấy.
- Giống nhau: đều truyền giá trị vào hàm khi hàm được gọi.
- Khác nhau:
- Truyền tham trị (Pass by value): truyền giá trị của biến vào hàm.
- Truyền tham chiếu (Pass by reference): truyền địa chỉ của biến vào hàm.
Truyền tham trị – Pass by value
Ý tưởng
Khi truyền biến vào hàm theo cách truyền tham trị, giá trị của biến sẽ được sao chép thành một bản sao trong bộ nhớ, việc thực hiện các phép tính toán trong hàm đối với biến này đều thực hiện trên bản sao đã tạo ra, nghĩa là nó sẽ làm việc trên bản sao.
(Giống như bạn photo giấy khai sinh rồi đem ra xã đóng dấu lên bản sao để công chứng đó, chúng ta làm việc đóng dấu lên bản sao photo chứ không tác động trực tiếp trên bản gốc).
Kết quả
Giá trị của biến được truyền hàm vào không thay đổi.
(Bản gốc bạn đem đi photo ra bản sao như nào thì nó y chang như vậy)
Cách sử dụng
Không cần thêm ký hiệu gì đặc biệt trước biến được truyền vào hàm cả.
Ví dụ
#include <iostream> using namespace std; void go_up(int a){ a++; } int main(){ int n = 2; go_up(n); cout<<"Ket qua: "<<n; }
Kết quả khi chạy chương trình:
Ket qua: 2
Giải thích
Biến n
được truyền vào hàm go_up(int a)
theo cách truyền tham trị thì biến
của hàm a
go_up
và biến
là hai biến độc lập, do đó hàm làm việc trên bản sao của n
n
, cho nên sau khi tăng giá trị của a
trong hàm lên 1, giá trị của biến
vẫn không thay đổi sau khi kết thúc gọi hàm, n
vẫn bằng 2.n
Ví dụ thực tế
Giả sử bạn mua 8 bộ quần áo trên Shopee và giao hàng tới số nhà 68.
#include <iostream> using namespace std; int Home(int x) //Gửi cho Shipper thì bạn sẽ gửi hình bóng ngôi nhà Home(int &) hay địa chỉ ngôi nhà Home(int &x) { return x = 8; //Shipper cần giao 8 bộ quần áo tại địa chỉ int x bên trên } int main() { int x = 68; //Giả sử căn nhà Home có tên là 68 Home(x); //Lấy thông tin của ngôi nhà cout<<x; }
Kết quả trả về là:
Ket qua: 68
Oh! Kết quả trả về là 68, tại sao chúng ta không nhận được 8 bộ quần áo, bởi vì anh Shipper chỉ biết giao đến nhà có tên 68 nhưng không biết nó ở phường, tỉnh nào.
Trong hàm main()
, khi truyền int x = 68
vào hàm Home(int x)
, nó tạo ra một biến x
khác (bản sao) rồi gán giá trị truyền vào int x = 68
cho biến x
đó để làm 1 công việc nào đó trong hàm Home(int x)
, sau khi kết thúc hàm thì biến mình truyền dữ liệu vào chả thay đổi gì cả. Nghĩa là mình khai báo int x = 68
ở dòng số 9, đem nó đi sang hàm khác rồi lại hiển thị nó ở hàm main()
– dòng 11 thì giá trị vẫn như lúc khai báo, nó giống như kiểu biến cục bộ vậy.
Truyền tham chiếu – Pass by reference
Ý tưởng
Đối với truyền tham chiếu, địa chỉ của biến sẽ được truyền vào hàm, chính vì thế việc thực hiện các phép tính toán trong hàm đối với biến này đều thực hiện trực tiếp trên địa chỉ chứa giá trị của biến đó.
Bạn có thể hiểu là: bạn mua hàng trên Shopee và bạn cần gửi địa chỉ nhận hàng (địa chỉ của biến) cho Shipper, vì vậy, Shipper sẽ đi giao hàng theo đúng địa chỉ mà bạn đã cung cấp.
Kết quả
Giá trị của biến được truyền vào hàm sẽ thay đổi. Nó đặc biệt sử dụng trực tiếp biến truyền vào, không phải tạo bản sao như truyền tham trị nên truyền tham biến tốc độ phần này xử lý nhanh hơn (Tối ưu).
Cách sử dụng
Thêm ký hiệu dấu
vào trước biến được truyền vào hàm.&
Ví dụ
#include <iostream> using namespace std; void go_up(int &a){ a++; } int main(){ int n = 2; go_up(n); cout<<"Ket qua: "<<n; }
Kết quả khi chạy chương trình:
Ket qua: 3
Giải thích
Biến
được truyền vào hàm n
theo cách truyền tham chiếu, do đó hàm làm việc trực tiếp trên địa chỉ của go_up(int &a)
, cho nên sau khi tăng giá trị của n
trong hàm lên 1, giá trị của biến a
vẫn sẽ thay đổi sau khi kết thúc gọi hàm, n
sẽ bằng 3.n
Ví dụ thực tế
Giả sử bạn mua 8 bộ quần áo trên Shopee và giao hàng tới nhà 68, lần này, bạn đã đưa cho Shipper địa chỉ nhà cụ thể bằng cách thêm ký tự đặc biệt &
#include <iostream> using namespace std; int Home(int &x) //Gửi cho Shipper thì bạn sẽ gửi hình bóng ngôi nhà Home(int &) hay địa chỉ ngôi nhà Home(int &x) { return x = 8; //Shipper cần giao 8 bộ quần áo tại địa chỉ int x bên trên } int main() { int x = 68; //Giả sử căn nhà Home có tên là 68 Home(x); //Lấy thông tin của ngôi nhà cout<<x; }
Kết quả trả về là:
Ket qua: 8
Oh! Thật tuyệt vời!, chúng ta đã nhận được 8 bộ quần áo, bởi vì anh Shipper chỉ biết giao đến địa chỉ cụ thể của số nhà 68.
Khi mình truyền một biến int x = 68
vào hàm Home(int &x)
thì nó dùng biến x = 68
đó để tính toán các kiểu trong hàm(nếu có), khi ra khỏi hàm thì biến được truyền vào đó bị thay đổi giá trị. Trong trường hợp này, trước khi vào hàm Home(int &x)
nó mang giá trị 68, nhưng khi ở bên trong hàm, giá trị của x đã bị thay đổi, cụ thể là x = 8
nên khi ra khỏi hàm x sẽ mang giá trị thay đổi đó, và chúng ta sẽ nhận được kết quả là 8 ở dòng 11.
Trường hợp sử dụng
Cuối cùng, truyền tham trị được sử dụng trong trường hợp bạn không muốn thay đổi giá trị của biến truyền vào, truyền tham chiếu được sử dụng khi bạn muốn thay đổi giá trị của biến được truyền vào.
Một ví dụ kinh điển trong sử dụng truyền tham chiếu đó là hàm hoán vị
#include <iostream> using namespace std; void hoanvi(int &a, int &b){ int tg = a; a = b; b = tg; } int main(){ int a = 6; b = 8; cout<<"Truoc khi hoan vi a = "<<a<<" va b = "<<b; cout<<endl; hoanvi(a,b); cout<<"Sau khi hoan vi a = "<<a<<" va b = "<<b; }
Giải thích
Chương trình chạy đến dòng 10 thì hiển thị hai thông số đầu vào là 6 và 8 đã được khai báo int a = 6; b = 8
tại dòng 9.
Sau đó nó gọi hàm hoanvi(a,b)
tại dòng 12 để làm việc:
- Khi nhận được lời gọi, nó truyền 2 biến
a = 6
vàb = 8
vào trong hàmhoanvi(int &a, int &b)
. - Dòng 4: khai báo
tg = a //a = 6 nên tg = 6
, - Dòng 5:
a = b //Biến a ban đầu bằng 6 nhưng đã thay đổi bằng biến b = 8
, - Dòng 6:
b = tg // Biến b ban đầu bằng 8 nhưng gán bằng tg, mà dòng 4 có tg = 6 nên b = 6
Kết quả sau khi truyền tham chiếu đó là giá trị của biến vào hàm sẽ thay đổi khi hàm kết thúc, chúng ta nhận được kết quả 8 6 khi hiển thị và code tại dòng 13.
Ví dụ trên cho thấy trong một số trường hợp, truyền tham trị không giải quyết được vấn đề, ta cần phải sử dụng truyền tham chiếu. Vậy bạn đã hiểu được cách sử dụng nó chưa, hãy để lại ý kiến phần bình luận nhé.