1. Trang chủ
  2. » Công Nghệ Thông Tin

8 7 con trỏ trỏ đến con trỏ lập trình C++ daynhauhoc.com

7 113 0
Tài liệu được quét OCR, nội dung có thể không chính xác

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 1,23 MB

Nội dung

Trang 1

8.7 Con trỏ trỏ đến con trỏ Thursday, September 21, 2017 7:47 PM

Được cắt từ: https://cpp.daynhauhoc.com/8/7-con-tr-tr-den-con-tr/

Trong bài học này, chúng ta sẽ cùng nhau tìm hiểu một khái niệm nâng cao của con trỏ: "Con trỏ trỏ đến con tro"

Pointer to poiïinter là một loại con trỏ dùng để lưu trữ địa chỉ của biến con trỏ

Minh lẫy ví dụ về việc sử dụng con trỏ thông thường: int value;

int *ptr = &value;

Chúng ta gán được địa chỉ của biến value cho con tro ptr vi bién value la

bien kiéu int, va su dung toan tu address-of cho bién value sé tra ve gia

trị kiểu (int *) giống với kiểu dữ liệu cua con tro ptr

Trang 2

Như chúng ta thấy, chúng ta cần khai báo biến có kiểu dữ liệu (int **) để có thể gán địa chỉ của con trỏ kiểu (int *) cho nó Let's try:

int *ptr = NULL; int **p to_p = &ptr;

Con trỏ p_to_p được gọi là một Pointer to pointer

Cũng tương tự như khi sử dụng con trỏ thông thường, chúng ta có thể sử dụng toán tử dereference cho một Pointer to pointer

int main() {

int value = 100;

int *ptr = &value; int **p to_p = &ptr;

cout << p to p << endl; //print address of ptr

cout << *p to_p << endl; //print address which hold by ptr cout << **p to_p << endl; //print value at address which hold by ptr

return 0;

}

Bản chất của Pointer to pointer vẫn là một pointer, nên khi truy xuất giá trị của p_to_p chúng ta lấy được địa chỉ mà nó trỏ đến (địa chỉ của biến ptr)

p_to_p; //la &ptr

Khi chung ta su’ dung 1 toan tt dereference cho 1 pointer to pointer, cũng đồng nghĩa chúng ta dang truy xuất đến giá trị tại địa chỉ mà con trỏ ptr nằm giữ (địa chỉ đang được lưu trữ trong biến ptr)

*p to_p; //la ptr

Va khi st? dung 2 toan tt’ dereference cho 1 pointer to pointer, c6 thé viết lại như sau:

*(*p top); //là *ptr

Chúng ta có thể thấy việc sử dụng pointer to pointer cũng tương tự như việc đi hỏi tìm một người bạn mà không biết nhà nó ở đâu, chỉ biết nhà của những người biết vê nó Vậy là chúng ta đi hỏi từng người một

Vi du chung ta la A, dang can gap C nhưng không biết nó ở đâu, chúng ta hỏi (sử dụng toán tử dereference) chú B thì chú B bảo đến địa chỉ mà C đang ở, chúng ta đến địa chỉ mà chú B nắm giữ và truy xuất vào đó là sẽ

tìm được thẳng C

Tóm tắt lại ví dụ trên, chúng ta có thể viết:

A giữ địa chỉ nhà chú B => A = &B;

Trang 3

Nhu vay:

(*A) tuong duong (*(&B)) tuong duong &C; *(*A) tương đương *(*(&B)) tương đương C; Áp dụng lại cho ví dụ: int main() { int value = 100; int *ptr = &value; int **p to _p = &ptr;

cout << p_ top << endl; //print address of ptr

cout << *p to_p << endl; //print address which hold by ptr cout << **p to_p << endl; //print value at address which hold by ptr

return 0;

}

Chung ta co thé viét:

p to p giữ địa chỉ của ptr => p_to p = &ptr;

ptr gif dia chi cua value => ptr = &value; Nhu vay:

(*p_to_p) tương duong ptr tuong đương &value;

**b_to p tương đương *#ptr tương đương value; Kết quả: **p to p *p to TP p_to TP a “ak &ptr &value | 100 |

Chúng ta không thể gán trực tiếp như sau:

int **p to_p = &&value; //not valid

Trang 4

Và cũng tương tự như những con trỏ khác, Pointer to pointer có thể gán giá trị NULL: int **p to_p = NULL; Array of pointers Pointer to pointer có thể được dùng để quản lý mảng một chiều kiểu con trỏ (int *[]) Ví dụ: int main() { int *p1 = NULL; int *p2 = NULL; int *p3 = NULL; int *p[] = { p1, p2, p3 }; int **p to_p = p; return 0; }

Trong trường hợp này, p_to_p[0] tương đương với p[0]

Thông thường, chúng ta sẽ sử dụng pointer to pointer để quản lý vùng nhớ được cấp phát trên Heap cho mảng một chiêu chứa các con trỏ int *p1 = NULL; int *p2 = NULL; int *p3 = NULL; int **p to_p = new int*[3]; p_to_p[9] = p1; p_to_p[1] = p2; p_to_p[2] = p3; delete[] p_to p;

Tương tự như con trỏ kiểu (int *) dùng để trỏ đến mảng các phần tử kiểu int, con trỏ kiểu (int **) dùng để trỏ đến mảng các phần tử kiểu (¡int *)

2D dynamically allocated array

Một cách sử dụng khác của Pointer to pointer la dung dé quan ly mang hai chiêu được cấp phát trén Heap

Với mảng hai chiêu cấp phát trên Stack, chúng ta chỉ cần khai báo như

sau:

int arr2D[5][19];

Nhưng với mảng hai chiều cấp phát trên Heap sẽ rắc rối hơn

Trang 5

chiêu có cùng kích thước Chúng ta cũng đã biết cách cấp phát vùng nhớ cho mảng một chiều trên Heap bằng cách dùng toán tử new đi kèm với toán tử [ ] Ví dụ:

int *arr1 = new int[10]; int *arr2 = new int[10];

h=

Như vậy, một mảng các con trỏ được dùng để quản lý tập hợp các mảng một chiêu này sẽ tạo thành mảng 2 chiều Ví dụ:

int *pToArrPtr[3];

for(int i = 0; 1 < 3; i++)

{ }

Kết quả của đoạn chương trình này cho chúng ta một vùng nhớ có kích

thước (3 x 5) phần tử kiểu int Và chúng ta có thể truy xuất từng giá trị

thông qua con trỏ pToArrPtr:

Trang 6

C:\WINDOWS\system32\cmd.exe — T x

Kết quả hoàn toàn giống với mảng hai chiêu thông thường Nhưng lúc

này, 3 con trỏ pToArrPtr[0] và pToArrPtr[ 1 | và pToArrPtr|2] van là biến được cấp phát trên Stack Để chuyển những con trỏ quản lý các mảng

một chiêu con này sang Heap, chúng ta cần sử dụng Pointer to pointer Dưới đây là toàn bộ chương trình mẫu cho việc cấp phát và giải phóng

vùng nhớ 2 chiêu hoạt động tương tự như mảng hai chiều thông thường:

†include <1ostream>

using namespace std; int main() {

int **pToArrPtr;

//Cấp phát vùng nhớ cho 3 con trỏ kiểu (int *)

pToArrPtr = new int*[3];

//Mỗi con trỏ kiểu (int *) sẽ quản lý 5 phần tử kiểu int

Trang 7

for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { cout << pToArrPtr[i|[j] << " "3 } cout << endl; } //Giai phóng vùng nhớ cho từng dãy vùng nhớ mà 3 con trỏ đang quản lý for (int 1 = 6; 1 < 3; i++) { delete[ ] pToArrPtr[i]; } //Giải phóng cho 3 biến con trỏ chịu sự quản lý của pToArrPtr delete[ ] pToArrPtr; return 0; }

Pointer to pointer to pointer to

Chúng ta có thể khai báo những con trỏ có dạng như sau:

int ***ptrX3;

int ******ptrX6G;

Tuy nhiên, việc thao tác với những con trỏ như thế này khá phức tạp và rất ít gặp trong thực tế nên mình không đề cập trong bài học này

Tổng kết

Pointer to pointer là một phần nâng cao của con trỏ Việc thao tác cấp phát và giải phóng vùng nhớ khá phức tạp Do đó, các bạn mới học có thể hoàn toàn bỏ qua bài học này Mình cũng khuyên các bạn nên tránh sử dụng Pointer to pointer trừ khi không còn giải pháp nào thay thế Hẹn gặp lại các bạn trong bài học tiếp theo trong khóa học lập trình C++ hướng thực hành

Mọi ý kiến đóng góp hoặc thắc mắc có thể đặt câu hỏi trực tiếp tại diễn

đàn

Ngày đăng: 25/10/2017, 20:36