Trong C++ việc viết hàm để xử lí là rất thường xuyên, chúng ta thường truyền dữ liệu vào hàm theo 2 cách đó là truyền tham chiếu và tham trị.
1. Tham trị (pass by value)
Truyền tham trị là truyền cho đối số một bản sao.
- Ví dụ:
#include <bits/stdc++.h>
using namespace std;
void changeValue(int x)
{
x = 2;
}
int main()
{
int x = 0;
changeValue(x);
cout<<x;
return 0;
}
- Kết quả ra 0
Xét hàm changeValue(int x);
x
ở hàm này là một bản sao khác của x ở hàm main
, và x
là một biến cục bộ bên trong thân hàm nên việc thay đổi x = 2
ở thân hàm changeValue
hoàn toàn không ảnh hưởng gì tới giá trị thực sự của biến x
ở hàm main
. (Nó chỉ thay đổi giá trị bản sao của x
ở bên trong hàm changeValue
)
Lỗi thường gặp khi dùng cách truyền tham trị là ta khai báo lại 1 lần nữa tham số truyền vào, ví dụ:
void changeValue(int x)
{
int x; // lỗi
x = 2;
}
2. Tham chiếu (pass by reference)
Ở trên thì chúng ta đã biết truyền tham trị là truyền cho nó một bản sao, thì bây giờ truyền tham chiếu chính là cách chúng ta truyền cho nó một bản gốc thông qua địa chỉ ‘&
‘.
Ví dụ với hàm changeValue(int &x);
thì đối số x
ở đây lúc này là một tham chiếu.
Với cách truyền này dữ liệu của lời gọi có thể được sửa đổi bởi hàm được gọi.
- Ví dụ:
#include <bits/stdc++.h>
using namespace std;
void changeValue(int &x) // tham chiếu
{
x = 2;
}
int main()
{
int x = 0;
changeValue(x);
cout<<x;
return 0;
}
- Như chúng ta đã biết khi khai báo một biến
int x = 0;
thìx
ở đây đã được bộ nhớ cấp phát cho một địa chỉ và một giá trị, việc hàmchangeValue(int &x);
thìx
ở hàm này đã tiếp nhận địa chỉ củax
ở hàmmain
nên khix
thay đổi giá trị ở hàmchangeValue
dẫn tới việcx
ở hàm main thay đổi giá trị theo.
Chúng ta thường sử dụng cách truyền tham chiếu cho các trường hợp nhập dữ liệu đầu vào. Ví dụ như viết một hàm nhập n từ bàn phím, viết một hàm nhập dữ liệu cho vector, viết một hàm đổi giá trị giữa 2 số a và b,…
Khi sử dụng đối số tham chiếu xảy ra rủi ro về dữ liệu bị thay đổi không như ý muốn là rất cao.
Để bảo vệ dữ liệu tránh được những rủi ro ta thường sử dụng từ khóa const
với cú pháp như sau: void function(const int arg){}
khi dùng từ khóa const
phía trước ta đã coi như arg
là một đối số hằng, và nó có nhiệm vụ chỉ đọc, nếu ta cố tình thay đổi nó sẽ báo lỗi “[Error] assignment of read-only reference”.
Dùng đối số hằng có quan trọng không?
Theo ý kiến cá nhân của mình thì nó cực kì quan trọng trong các trường hợp đối số là các cấu trúc dữ liệu ví dụ như vector; khi ta truyền đối số là một vector có kích thước là n thì với cách truyền tham trị nó sẽ phải gọi hàm tạo của vector để tạo 1 bản sao của vector đó nên nó sẽ mất thời gian O(n); còn với cách truyền tham chiếu nó sẽ truy cập trực tiếp vector đó nên nó chỉ mất thời gian là O(1). Khi vector kích thước dài thì code của chúng ta nhanh hơn đáng kể phải không?
Do đó cách truyền này vừa nhanh lại vừa bảo vệ được dữ liệu của đối số.
- Trong một hàm chúng ta hoàn toàn có thể vừa truyền tham chiếu và vừa truyền được tham trị. (lưu ý tới thứ tự truyền tham số khi gọi hàm)
- Ví dụ:
void thuongtet(int &tien_thuong, int luong) {}
- Ví dụ:
- Lưu ý đối với mảng, khi khai báo một mảng ở hàm thì mạc định nó là một tham chiếu chứ không phải là tham trị.
void function(int &a[]){} // lỗi
void function(int a[]){} // true
TỔNG KẾT
Khi dùng tham trị thì x ở hàm changeValue và ở main 2 biến là độc lập với nhau.
Khi dùng tham chiếu thì x ở hàm changeValue và ở main 2 biến là một.
Bài viết có gì sai sót mong các bạn phản hồi để mình có thể sửa đổi và hoàn thiện nó hơn nhé. Cảm ơn các bạn đã đọc và share.
Để lại một phản hồi
Bạn phải đăng nhập để gửi phản hồi.