Con trỏ là gì?
Trong C ++, một con trỏ tham chiếu đến một biến giữ địa chỉ của một biến khác. Giống như các biến thông thường, con trỏ có một kiểu dữ liệu. Ví dụ, một con trỏ kiểu số nguyên có thể chứa địa chỉ của một biến kiểu số nguyên. Một con trỏ kiểu ký tự có thể chứa địa chỉ của một biến kiểu ký tự.
Bạn sẽ thấy một con trỏ như một đại diện tượng trưng của một địa chỉ bộ nhớ. Với con trỏ, chương trình có thể mô phỏng cuộc gọi theo tham chiếu. Họ cũng có thể tạo và thao tác các cấu trúc dữ liệu động. Trong C ++, một biến con trỏ đề cập đến một biến trỏ đến một địa chỉ cụ thể trong bộ nhớ được trỏ bởi một biến khác.
Trong hướng dẫn C ++ này, bạn sẽ học:
- Con trỏ là gì?
- Địa chỉ trong C ++
- Cú pháp khai báo con trỏ
- Toán tử tham chiếu (&) và toán tử tham chiếu (*)
- Con trỏ và Mảng
- Con trỏ NULL
- Con trỏ của các biến
- Ứng dụng của con trỏ
- Ưu điểm của việc sử dụng Con trỏ
Địa chỉ trong C ++
Để hiểu con trỏ C ++, bạn phải hiểu cách máy tính lưu trữ dữ liệu.
Khi bạn tạo một biến trong chương trình C ++ của mình, nó sẽ được gán một số không gian cho bộ nhớ máy tính. Giá trị của biến này được lưu trữ ở vị trí được chỉ định.
Để biết vị trí trong bộ nhớ máy tính nơi dữ liệu được lưu trữ, C ++ cung cấp toán tử & (tham chiếu). Toán tử trả về địa chỉ mà một biến chiếm giữ.
Ví dụ: nếu x là một biến, & x trả về địa chỉ của biến.
Cú pháp khai báo con trỏ
Khai báo C ++ theo cú pháp sau:
datatype *variable_name;
- Kiểu dữ liệu là kiểu cơ sở của con trỏ phải là kiểu dữ liệu C ++ hợp lệ.
- Tên_biến phải là tên của biến con trỏ.
- Dấu hoa thị được sử dụng ở trên để khai báo con trỏ tương tự như dấu hoa thị được sử dụng để thực hiện phép toán nhân. Đó là dấu hoa thị đánh dấu biến dưới dạng con trỏ.
Đây là một ví dụ về khai báo con trỏ hợp lệ trong C ++:
int *x; // a pointer to integerdouble *x; // a pointer to doublefloat *x; // a pointer to floatchar *ch // a pointer to a character
Toán tử tham chiếu (&) và toán tử tham chiếu (*)
Toán tử tham chiếu (&) trả về địa chỉ của biến.
Toán tử dereference (*) giúp chúng ta lấy giá trị đã được lưu trong một địa chỉ bộ nhớ.
Ví dụ:
Nếu chúng ta có một biến có tên là num, được lưu trữ trong địa chỉ 0x234 và lưu trữ giá trị 28.
Toán tử tham chiếu (&) sẽ trả về 0x234.
Toán tử tham chiếu (*) sẽ trả về 5.
Ví dụ 1:
#includeusing namespace std;int main() {int x = 27;int *ip;ip = &x;cout << "Value of x is : ";cout << x << endl;cout << "Value of ip is : ";cout << ip<< endl;cout << "Value of *ip is : ";cout << *ip << endl;return 0;}
Đầu ra:
Cách thức hoạt động:
Đây là ảnh chụp màn hình của mã:
Giải thích mã:
- Nhập tệp tiêu đề iostream. Điều này sẽ cho phép chúng tôi sử dụng các chức năng được xác định trong tệp tiêu đề mà không bị lỗi.
- Bao gồm không gian tên std để sử dụng các lớp của nó mà không cần gọi nó.
- Gọi hàm main (). Logic chương trình nên được thêm vào trong phần thân của hàm này. Dấu {đánh dấu phần bắt đầu của phần thân của hàm.
- Khai báo một biến số nguyên x và gán cho nó một giá trị là 27.
- Khai báo một biến con trỏ * ip.
- Lưu trữ địa chỉ của biến x trong biến con trỏ.
- In một số văn bản trên bảng điều khiển.
- In giá trị của biến x ra màn hình.
- In một số văn bản trên bảng điều khiển.
- In địa chỉ của biến x. Giá trị của địa chỉ được lưu trữ trong biến ip.
- In một số văn bản trên bảng điều khiển.
- In giá trị được lưu trữ tại địa chỉ của con trỏ.
- Chương trình sẽ trả về giá trị khi thực hiện thành công.
- Cuối phần thân của hàm main ().
Con trỏ và Mảng
Mảng và con trỏ hoạt động dựa trên một khái niệm có liên quan. Có những điều khác nhau cần lưu ý khi làm việc với mảng có con trỏ. Bản thân tên mảng biểu thị địa chỉ cơ sở của mảng. Điều này có nghĩa là để gán địa chỉ của một mảng cho một con trỏ, bạn không nên sử dụng dấu và (&).
Ví dụ:
p = arr;
Ở trên là đúng vì arr đại diện cho địa chỉ của mảng. Đây là một ví dụ khác:
p = &arr;
Điều trên là không chính xác.
Chúng ta có thể chuyển đổi ngầm một mảng thành một con trỏ. Ví dụ:
int arr [20];int * ip;
Dưới đây là một hoạt động hợp lệ:
ip = arr;
Sau khai báo trên, ip và arr sẽ tương đương nhau, và chúng sẽ chia sẻ thuộc tính. Tuy nhiên, một địa chỉ khác có thể được gán cho ip, nhưng chúng ta không thể gán bất cứ thứ gì cho arr.
Ví dụ 2:
Ví dụ này cho thấy cách duyệt qua một mảng bằng cách sử dụng con trỏ:
#includeusing namespace std;int main() {int *ip;int arr[] = { 10, 34, 13, 76, 5, 46 };ip = arr;for (int x = 0; x < 6; x++) {cout << *ip << endl;ip++;}return 0;}
Đầu ra:
Đây là ảnh chụp màn hình của mã:
Giải thích mã:
- Khai báo một biến con trỏ số nguyên ip.
- Khai báo một mảng có tên arr và lưu trữ 6 số nguyên vào đó.
- Gán arr cho ip. Ip và arr sẽ trở thành tương đương.
- Tạo vòng lặp for. Biến vòng lặp x được tạo để lặp qua các phần tử của mảng từ chỉ số 0 đến 5.
- In các giá trị được lưu trữ tại địa chỉ IP của con trỏ. Một giá trị sẽ được trả về cho mỗi lần lặp và tổng cộng 6 lần lặp lại sẽ được thực hiện. Endl là một từ khóa C ++ có nghĩa là dòng kết thúc. Hành động này cho phép bạn di chuyển con trỏ đến dòng tiếp theo sau mỗi giá trị được in. Mỗi giá trị sẽ được in trong một dòng riêng lẻ.
- Để di chuyển con trỏ đến vị trí int tiếp theo sau mỗi lần lặp.
- Kết thúc vòng lặp for.
- Chương trình phải trả về một cái gì đó sau khi thực hiện thành công.
- Kết thúc phần thân của hàm main ().
Con trỏ NULL
Nếu không có địa chỉ chính xác được gán, thì biến con trỏ có thể được gán NULL. Nó nên được thực hiện trong quá trình khai báo. Một con trỏ như vậy được gọi là một con trỏ null. Giá trị của nó bằng 0 và được định nghĩa trong nhiều thư viện tiêu chuẩn như iostream.
Ví dụ 3:
#includeusing namespace std;int main() {int *ip = NULL;cout << "Value of ip is: " << ip;return 0;}
Đầu ra:
Đây là ảnh chụp màn hình của mã:
Giải thích mã:
- Khai báo một biến con trỏ ip và gán cho nó một giá trị NULL.
- In giá trị của biến con trỏ ip cùng với một số văn bản trên bảng điều khiển.
- Chương trình phải trả về giá trị khi hoàn thành thành công.
- Cuối phần thân của hàm main ().
Con trỏ của các biến
Với C ++, bạn có thể thao tác dữ liệu trực tiếp từ bộ nhớ của máy tính.
Không gian bộ nhớ có thể được gán hoặc gán lại theo ý muốn. Điều này được thực hiện bởi các biến Con trỏ.
Biến con trỏ trỏ đến một địa chỉ cụ thể trong bộ nhớ của máy tính được trỏ tới bởi một biến khác.
Nó có thể được khai báo như sau:
int *p;
Hoặc là,
int* p;
Trong ví dụ bạn, chúng tôi đã khai báo biến con trỏ p.
Nó sẽ giữ một địa chỉ bộ nhớ.
Dấu hoa thị là toán tử tham chiếu có nghĩa là một con trỏ đến.
Con trỏ p đang trỏ đến một giá trị nguyên trong địa chỉ bộ nhớ.
Ví dụ 4:
#includeusing namespace std;int main() {int *p, x = 30;p = &x;cout << "Value of x is: " << *p;return 0;}
Đầu ra:
Đây là ảnh chụp màn hình của mã:
Giải thích mã:
- Khai báo một biến con trỏ p và một biến x có giá trị là 30.
- Gán địa chỉ của biến x cho p.
- In giá trị của biến con trỏ p cùng với một số văn bản trên bảng điều khiển.
- Chương trình phải trả về giá trị khi hoàn thành thành công.
- Cuối phần thân của hàm main ().
Ứng dụng của con trỏ
Các hàm trong C ++ chỉ có thể trả về một giá trị. Hơn nữa, tất cả các biến được khai báo trong một hàm được cấp phát trên ngăn xếp lệnh gọi hàm. Ngay sau khi hàm trả về, tất cả các biến ngăn xếp sẽ bị hủy.
Các đối số cho hàm được truyền theo giá trị và bất kỳ sửa đổi nào được thực hiện trên các biến sẽ không thay đổi giá trị của các biến thực tế được truyền. Ví dụ sau giúp minh họa khái niệm này: -
Ví dụ 5:
#includeusing namespace std;void test(int*, int*);int main() {int a = 5, b = 5;cout << "Before changing: << endl;cout << "a = " << a << endl;cout << "b = " << b << endl;test(&a, &b);cout << "\nAfter changing" << endl;cout << "a = " << a << endl;cout << "b = " << b << endl;return 0;}void test(int* n1, int* n2) {*n1 = 10;*n2 = 11;}
Đầu ra:
Đây là ảnh chụp màn hình của mã:
Giải thích mã:
- Tạo một nguyên mẫu của một hàm có tên là test sẽ nhận hai tham số nguyên.
- Gọi hàm main (). Chúng tôi sẽ thêm logic chương trình vào bên trong phần thân của nó.
- Khai báo hai biến số nguyên a và b, mỗi biến có giá trị là 5.
- In một số văn bản trên bảng điều khiển. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo.
- In giá trị của biến a trên bảng điều khiển cùng với văn bản khác. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo.
- In giá trị của biến b trên bảng điều khiển cùng với văn bản khác. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo.
- Tạo một hàm có tên test () lấy địa chỉ của biến a và b làm tham số.
- In một số văn bản trên bảng điều khiển. \ N sẽ tạo một dòng trống mới trước khi văn bản được in. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo sau khi văn bản được in.
- In giá trị của biến a trên bảng điều khiển cùng với văn bản khác. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo.
- In giá trị của biến b trên bảng điều khiển cùng với văn bản khác. Endl (dòng kết thúc) sẽ di chuyển con trỏ để bắt đầu in ở dòng tiếp theo.
- Chương trình phải trả về giá trị khi hoàn thành thành công.
- Cuối phần thân của hàm main ().
- Định nghĩa kiểm tra hàm (). Hàm nên nhận hai biến con trỏ nguyên * n1 và * n2.
- Gán biến con trỏ * n1 một giá trị là 10.
- Gán biến con trỏ * n2 một giá trị là 11.
- Phần cuối của phần thân của hàm test ().
Ngay cả Mặc dù vậy, các giá trị mới được gán cho biến a và b bên trong hàm kiểm tra, sau khi lệnh gọi hàm hoàn tất, điều tương tự không được phản ánh trong hàm main bên ngoài.
Sử dụng con trỏ làm đối số của hàm giúp chuyển địa chỉ thực của biến trong hàm và tất cả các thay đổi được thực hiện trên biến sẽ được phản ánh trong hàm bên ngoài.
Trong trường hợp trên, hàm 'test' có địa chỉ của các biến 'a' và 'b.' Hai biến này có thể truy cập trực tiếp từ hàm 'test' và do đó bất kỳ thay đổi nào được thực hiện đối với các biến này đều được phản ánh trong hàm người gọi 'main.'
Ưu điểm của việc sử dụng Con trỏ
Đây là ưu / lợi ích của việc sử dụng Pointers
- Con trỏ là các biến lưu trữ địa chỉ của các biến khác trong C ++.
- Hàm có thể sửa đổi và trả về nhiều hơn một biến bằng cách sử dụng con trỏ.
- Bộ nhớ có thể được cấp phát động và khử cấp phát bằng cách sử dụng con trỏ.
- Con trỏ giúp đơn giản hóa độ phức tạp của chương trình.
- Tốc độ thực thi của một chương trình được cải thiện bằng cách sử dụng con trỏ.
Tóm lược:
- Một con trỏ đề cập đến một địa chỉ giữ biến của một biến khác.
- Mỗi con trỏ có một kiểu dữ liệu hợp lệ.
- Một con trỏ là một biểu diễn tượng trưng của một địa chỉ bộ nhớ.
- Con trỏ cho phép các chương trình mô phỏng cuộc gọi theo tham chiếu và tạo và thao tác các cấu trúc dữ liệu động.
- Mảng và con trỏ sử dụng một khái niệm có liên quan.
- Tên mảng biểu thị cơ sở của mảng.
- Nếu bạn muốn gán địa chỉ của một mảng cho một con trỏ, không sử dụng dấu và (&).
- Nếu không có địa chỉ cụ thể để gán một biến con trỏ, hãy gán nó là NULL.