Trong C++, khi truyền dữ liệu vào hàm, có hai cách quan trọng cần hiểu là truyền giá trị và truyền địa chỉ.
Ví dụ:
void xl(int a)
{
a = 10;
}
int main()
{
int a = 2;
xl(a);
cout << a;
}Kết quả:
2
Khi gọi:
xl(a);
C++ sẽ sao chép giá trị của biến a vào biến a bên trong hàm.
main() xl()
a = 2 ---- copy ----> a = 2
|
↓
a = 10
Hai biến này nằm ở hai vùng nhớ khác nhau.
Vì vậy:
a trong hàm có giá trị 10.a trong main() vẫn có giá trị 2.Truyền địa chỉ thường sử dụng con trỏ.
Ví dụ:
void xl(int *a)
{
*a = 10;
}
int main()
{
int a = 2;
xl(&a);
cout << a;
}Kết quả:
10
Khi gọi:
xl(&a);
Ta truyền địa chỉ của biến a vào hàm.
main() xl()
a = 2
địa chỉ 1000
|
|-----------------> a = 1000
|
↓
*a = 10
|
↓
ô nhớ 1000 = 10
Do a trong hàm đang trỏ đến chính ô nhớ của biến a trong main(), nên giá trị của biến gốc bị thay đổi.
Ngoài truyền giá trị và truyền địa chỉ, C++ còn có truyền tham chiếu.
void xl(int &a)
{
a = 10;
}
int main()
{
int a = 2;
xl(a);
cout << a;
}
Kết quả:
10
Có thể hiểu a trong hàm là một tên khác (bí danh) của biến a trong main().
| Cách truyền | Khai báo hàm | Cách gọi | Có sửa biến gốc? |
|---|---|---|---|
| Truyền giá trị | void xl(int a) |
xl(a) |
Không |
| Truyền địa chỉ | void xl(int *a) |
xl(&a) |
Có |
| Truyền tham chiếu | void xl(int &a) |
xl(a) |
Có |
Ví dụ:
void xl(int a[])
{
a[0] = 11;
a[1] = 22;
}
int main()
{
int a[] = {1, 2};
xl(a);
cout << a[0] << endl;
cout << a[1] << endl;
}
Kết quả:
11 22
Khi truyền mảng vào hàm bằng dạng int a[], C++ xử lý tham số này về bản chất gần giống như một con trỏ đến phần tử đầu tiên của mảng.
Vì vậy, khi hàm thực hiện:
a[0] = 11; a[1] = 22;
thì các phần tử của mảng gốc cũng bị thay đổi.
Có thể ghi nhớ:
int a → Truyền giá trị → Có bản sao → Không sửa biến gốc int *a → Truyền địa chỉ → Truy cập biến gốc → Có thể sửa int &a → Truyền tham chiếu → Bí danh biến gốc → Có thể sửa int a[] → Mảng → Truyền vào hàm dưới dạng địa chỉ → Có thể sửa phần tử
So sánh truyền giá trị và truyền địa chỉ trong c++