Pointer trong C++ là gì?
Pointer trong C++ là biến dùng để lưu địa chỉ bộ nhớ của biến khác. Nói đơn giản, thay vì cầm trực tiếp giá trị 10, pointer giữ thông tin về nơi giá trị đó đang nằm trong bộ nhớ. Khi hiểu pointer trong C++ là gì, bạn sẽ dễ học hơn các phần như reference, mảng động, cấp phát bộ nhớ, và truyền dữ liệu vào hàm theo cách mạnh hơn.
Với người mới, phần khó nhất không phải cú pháp mà là cách nghĩ. Bình thường bạn quen với biến và giá trị. Với pointer, bạn cần thêm một lớp nữa là địa chỉ. Hãy tách rõ ba thứ sau:
- Biến gốc, ví dụ
x - Giá trị của biến, ví dụ
10 - Địa chỉ nơi biến được lưu trong bộ nhớ
Pointer sẽ lưu phần thứ ba. Khi nhìn như vậy, con trỏ không còn quá đáng sợ nữa.
Cú pháp cơ bản của pointer trong C++
#include <iostream>
using namespace std;
int main() {
int x = 10;
int* p = &x;
cout << x << endl;
cout << &x << endl;
cout << p << endl;
return 0;
}
Trong ví dụ trên:
&xlà địa chỉ của biếnxint* pnghĩa làplà con trỏ tới kiểuintpđang lưu địa chỉ củax
Bạn có thể hình dung như sau:
xlà chiếc hộp chứa số10&xlà địa chỉ căn phòng nơi chiếc hộp đó nằmplà mảnh giấy ghi lại địa chỉ căn phòng
Điều quan trọng là kiểu dữ liệu của pointer phải khớp với kiểu dữ liệu của biến mà nó trỏ tới. Nếu
x là int thì nên dùng int*. Nếu biến là double thì dùng double*. Việc này giúp C++ biết phải đọc bao nhiêu byte dữ liệu ở địa chỉ đó.
Bạn cũng nên biết rằng khi cout << p, chương trình thường in ra một địa chỉ dạng số hoặc mã hexa. Giá trị này có thể khác nhau mỗi lần chạy và đó là chuyện bình thường.
Cách dùng toán tử * và & trong C++
Toán tử & lấy địa chỉ, còn * lấy giá trị tại địa chỉ đó.
#include <iostream>
using namespace std;
int main() {
int x = 25;
int* p = &x;
cout << *p << endl;
*p = 50;
cout << x << endl;
return 0;
}
Khi bạn thay đổi *p, giá trị thật của x cũng thay đổi vì p đang trỏ trực tiếp vào x.
Đây là điểm mấu chốt nhất khi học cách dùng pointer trong C++. p và *p là hai thứ hoàn toàn khác nhau:
plà địa chỉ*plà giá trị nằm tại địa chỉ đó
Hãy xem thêm ví dụ này:
#include <iostream>
using namespace std;
int main() {
int diem = 8;
int* p = &diem;
cout << "Gia tri cua diem: " << diem << endl;
cout << "Dia chi cua diem: " << &diem << endl;
cout << "Gia tri trong p: " << p << endl;
cout << "Gia tri tai dia chi p: " << *p << endl;
return 0;
}
Ở đây, &diem và p sẽ giống nhau vì chúng cùng là địa chỉ của biến diem. Còn diem và *p sẽ giống nhau vì chúng cùng là giá trị thực đang được lưu.
Người mới thường nhầm ký hiệu * ở hai chỗ:
- Trong
int* p, dấu*là một phần của khai báo con trỏ - Trong
*p, dấu*là thao tác lấy giá trị tại địa chỉ đó
Ký hiệu giống nhau nhưng ý nghĩa phụ thuộc vào vị trí xuất hiện.
Khi nào pointer trong C++ hữu ích?
- Khi cần làm việc trực tiếp với địa chỉ bộ nhớ
- Khi truyền dữ liệu vào hàm để thay đổi biến gốc
- Khi làm việc với mảng, cấp phát động, hoặc cấu trúc dữ liệu nâng cao
Ví dụ, nếu bạn muốn viết hàm đổi giá trị của một biến từ bên ngoài, pointer là một cách làm quen thuộc:
#include <iostream>
using namespace std;
void capNhatGiaTri(int* p) {
*p = 99;
}
int main() {
int x = 15;
capNhatGiaTri(&x);
cout << x << endl;
return 0;
}
Hàm capNhatGiaTri không nhận bản sao của x. Nó nhận địa chỉ của x, sau đó đi tới đúng vị trí đó để sửa dữ liệu. Đây là lý do pointer rất hữu ích khi cần thao tác trực tiếp với dữ liệu gốc.
Trong các bài học sau, bạn sẽ thấy con trỏ còn xuất hiện khi làm việc với mảng, chuỗi ký tự kiểu cũ, hoặc bộ nhớ động. Nhưng ở bước đầu, chỉ cần nắm vững quan hệ giữa biến, địa chỉ, và giá trị là đủ.
Những lỗi thường gặp với pointer trong C++
- Dùng con trỏ chưa gán địa chỉ hợp lệ.
- Nhầm giữa
pvà*p. - Trỏ sai kiểu dữ liệu.
- Quên rằng thay đổi
*plà đang thay đổi biến gốc. - In hoặc dùng
*pkhipđang lànullptr.
int* p;
// Sai vi p chua tro den dia chi hop le
// cout << *p << endl;
Hãy luôn đảm bảo pointer đã được gán đúng trước khi dereference.
Một cách an toàn hơn khi mới học là khởi tạo con trỏ ngay lúc khai báo:
int x = 5;
int* p = &x;Hoặc nếu chưa có gì để trỏ tới, có thể cho con trỏ bằng nullptr:
int* p = nullptr;Khi đó bạn cần kiểm tra trước khi dùng:
if (p != nullptr) {
cout << *p << endl;
}Một lỗi khác của người mới là viết như sau:
int x = 10;
int* p = x;Đoạn này sai vì p cần một địa chỉ, còn x chỉ là giá trị. Cách đúng là int* p = &x;.
Bài tập thực hành
Tạo một biến so = 100, sau đó tạo pointer trỏ tới biến này. Hãy:
- In giá trị của
so - In địa chỉ của
so - In giá trị thông qua pointer
- Dùng pointer để đổi giá trị của
sothành200
Gợi ý khởi đầu:
#include <iostream>
using namespace std;
int main() {
int so = 100;
int* p = &so;
// Viet tiep tai day
return 0;
}
Sau khi làm xong, hãy tự trả lời hai câu hỏi:
- Vì sao
pvà&sogiống nhau? - Vì sao đổi
*pthìsocũng đổi theo?
Câu hỏi thường gặp về pointer trong C++
p và *p khác nhau thế nào?
p là địa chỉ mà con trỏ đang lưu. *p là giá trị nằm tại địa chỉ đó. Đây là khác biệt quan trọng nhất khi mới học pointer.
Vì sao pointer bị xem là khó?
Vì pointer liên quan trực tiếp đến bộ nhớ và địa chỉ, trong khi người mới thường quen nghĩ ở mức biến và giá trị. Khi bạn tách rõ “địa chỉ” và “giá trị”, pointer sẽ dễ hiểu hơn rất nhiều.
Có phải lúc nào cũng nên dùng pointer không?
Không. Ở nhiều tình huống cơ bản, biến thường hoặc reference sẽ dễ đọc hơn. Pointer chỉ nên dùng khi bạn thật sự cần làm việc với địa chỉ, cần truyền khả năng thay đổi dữ liệu gốc, hoặc phải xử lý cấu trúc dữ liệu yêu cầu con trỏ.
Dấu & trong pointer có giống & trong reference không?
Không hoàn toàn giống. Trong biểu thức như &x, dấu & có nghĩa là lấy địa chỉ của biến x. Còn trong khai báo int& y = x;, dấu & là cú pháp tạo reference. Ký hiệu giống nhau nhưng ngữ cảnh khác nhau.
Tóm tắt
Bạn đã hiểu pointer trong C++ là gì, cách khai báo con trỏ, cách dùng & để lấy địa chỉ và * để lấy giá trị tại địa chỉ đó. Bạn cũng đã thấy vì sao pointer có thể thay đổi trực tiếp biến gốc và những lỗi phổ biến như dereference con trỏ chưa hợp lệ hoặc nhầm giữa p với *p.
Nếu bạn nắm chắc bài này, bài kế tiếp sẽ nhẹ hơn nhiều, vì reference trong C++ cũng liên quan đến việc làm việc trực tiếp với dữ liệu gốc nhưng có cú pháp gọn và dễ đọc hơn.
Bài viết liên quan

Next.js là gì? Tại sao nên dùng Next.js để làm web?
Giới thiệu Next.js — framework React phổ biến nhất. Tìm hiểu ưu điểm, tính năng nổi bật và khi nào nên dùng.

Con bug đầu tiên trong cuộc đời lập trình viên
Câu chuyện hài hước về lần đầu gặp bug và mất 3 tiếng để tìm ra nguyên nhân chỉ là... thiếu dấu chấm phẩy.

Hướng dẫn cài đặt Python chi tiết trên Windows, macOS, Linux
Hướng dẫn từng bước cài đặt Python trên mọi hệ điều hành. Kèm cách kiểm tra và chạy chương trình đầu tiên.