Bài giảng Giới thiệu lập trình - Bài 9: Con trỏ
Nhắc Lại: cstring & Lớp string
char aCString[];
string stringVar;
Chuyển cstring sang string (hợp lệ)
stringVar = aCString;
Chuyển string sang cstring (không hợp lệ)
aCString = stringVar;
Giới Thiệu Lập TrìnhMảng Động
Hạn chế của mảng thông thường:
Phải khai báo độ dài trước
Độ dài mảng có thể không biết tới khi chạy
chương trình
Phải ước lượng độ dài lớn nhất
Lãng phí bộ nhớ
Mảng động
Có thể tăng và giảm khi cần thiết
Giới Thiệu Lập TrìnhGiải Phóng Mảng Động
Cũng được thực hiện khi chạy
d = new double[10];
// thao tác với d
delete [] d;
Giải phóng tất cả bộ nhớ cho mảng động
thông báo giải phóng bộ nhớ cho mảng
Vẫn chỉ tới vùng nhớ đó
Nên gán d = NULL;
Giới Thiệu L
23 trang |
Chia sẻ: thucuc2301 | Lượt xem: 779 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Bài giảng Giới thiệu lập trình - Bài 9: Con trỏ, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Giới Thiệu Lập Trình
Con Trỏ
TS. Lê Nguyên Khôi
Trường Đại học Công nghệ, ĐHQGHN
Nội Dung
1
Con trỏ
Biến kiểu con trỏ
Quản lý vùng nhớ
Toán tử con trỏ
Mảng động
Khai báo & sử dụng
Các phép toán với con trỏ
Giới Thiệu Lập Trình
Giới Thiệu
2
Định nghĩa:
Địa chỉ vùng nhớ máy tính của một biến
Vùng nhớ máy tính
Chia nhỏ thành các byte
Đánh số thứ tự lần lượt (hệ 16)
Địa chỉ được sử dụng làm tên cho biến
Con trỏ đã sử dụng
Truyền tham số theo kiểu tham chiếu
Địa chỉ của tham số được truyền
Giới Thiệu Lập Trình
Biến Con Trỏ
3
Con trỏ là “kiểu dữ liệu”
Kiểu địa chỉ vùng nhớ
Có thể dùng biến để lưu giá trị kiểu con trỏ
Không phải kiểu int, double
Địa chỉ của vùng nhớ dùng lưu dữ liệu kiểu
int, double
Ví dụ: double * p;
Khai báo p là biến kiểu con trỏ double
Lưu địa chỉ vùng nhớ kiểu double
Giới Thiệu Lập Trình
Biến Con Trỏ – Khai Báo
4
Khai báo con trỏ giống biến kiểu dữ liệu khác
Thêm * vào trước tên biến
Ký hiệu * phải đặt trước mỗi biến con trỏ
Ví dụ: int *p1, *p2, v1, v2;
p1, p2 biến kiểu con trỏ int
v1, v2 biến kiểu int
Sử dụng p1, p2 lưu địa chỉ các biến kiểu int
Sử dụng p1, p2 lưu địa chỉ của v1, v2
Giới Thiệu Lập Trình
Địa Chỉ & Số Nguyên
5
Con trỏ là địa chỉ
Địa chỉ là số nguyên
Con trỏ KHÔNG là số nguyên
C++ ép con trỏ phải được sử dụng như địa chỉ
Không thể được sử dụng như số nguyên
Mặc dù đó là số nguyên!!!
Giới Thiệu Lập Trình
Toán Tử &
6
Toán tử & trả về địa chỉ của biến
Dòng 4: đặt biến con trỏ p chỉ tới biến v1
p bằng địa chỉ của v1
Dòng 5: đặt biến con trỏ p chỉ tới biến v2
p chỉ tới v1
Giới Thiệu Lập Trình
1 {
2 int *p, v1, v2;
3 v1 = 10; v2 = 20;
4 p = &v1;
5 p = &v2;
6 } 0x22ff32
p
20
v2
0x22ff32
0x44ab12
p
10
v1
0x44ab12
Toán Tử *
7
Toán tử * truy xuất giá trị của vùng nhớ được
quản lý (lưu) bởi con trỏ
Dòng 4: in ra 10 (giá trị biến v1, mà p chỉ tới)
Dòng 6: in ra 20 (giá trị biến v2, mà p chỉ tới)
Giới Thiệu Lập Trình
1 {
2 int *p, v1, v2;
3 v1 = 10; p = &v1;
4 cout << *p;
5 v2 = 20; p = &v2;
6 cout << *p;
7 }
0x22ff32
p
20
v2
0x22ff32
0x44ab12
p
10
v1
0x44ab12
Toán Tử =
8
Gán giá trị
Dòng 3, 4: p chỉ tới v1, q chỉ tới v2
Dòng 5: sử dụng toán tử * truy cập vùng tới
nhớ con trỏ quản lý
*p là v1, *q là v2, dòng 5 tương đương v1 = v2;
Giới Thiệu Lập Trình
1 {
2 int v1 = 10, v2 = 20;
3 int *p = &v1;
4 int *p = &v2;
5 *p = *q;
6 } 0x22ff32
q
20
v2
0x22ff32
0x44ab12
p
10 20
v1
0x44ab12
Toán Tử =
9
Gán con trỏ
Dòng 3, 4: p chỉ tới v1, q chỉ tới v2
Dòng 5: gán p bằng q
p không quản lý v1
p và q cùng quản lý v2
Giới Thiệu Lập Trình
1 {
2 int v1 = 10, v2 = 20;
3 int *p = &v1;
4 int *p = &v2;
5 p = q;
6 } 0x22ff32
q
20
v2
0x22ff32
0x44ab12
p
10
v1
0x44ab12
0x22ff32
Bài Tập
10Giới Thiệu Lập Trình
1 {
2 int i = 10, j = 20, k;
3 int *p = &i;
4 int *q = &j;
5 *p += 1;
6 p = &k;
7 *p = *q;
8 p = q;
9 *p = i;
0 }
j
0x7756
p
0x64cc
p
0x16aa
k
0x9948
i
0x2232
Toán Tử new
11
Sử dụng toán tử new để tạo một vùng nhớ mới
cho con trỏ, vùng nhớ này không có tên
int * p = new int;
Khởi tạo một vùng nhớ mới cho con trỏ p, giá
trị tại vùng nhớ này không biết
int * p = new int(10);
Khởi tạo một vùng nhớ mới cho con trỏ p, giá
trị tại vùng nhớ này được khởi tạo là 10
Giới Thiệu Lập Trình
Bài Tập
12Giới Thiệu Lập Trình
1 {
2 int *p1, *p2;
3 p1 = new int;
4 *p1 = 10;
5 p2 = p1;
6 *p2 = 20;
7 p1 = new int;
8 *p1 = 30;
9 }
?p1
?p2
p1
?p2
?
p1
?p2
10
p1
p2
10
p1
p2
20
p1
p2 20
?
p1
p2 20
30
Toán Tử delete
13
Sử dụng toán tử delete để giải phóng vùng
nhớ động được tạo ra bởi toán tử new
Lưu ý: chỉ giải phóng vùng nhớ được tạo ra bởi
new, không phải xóa biến con trỏ p
Giới Thiệu Lập Trình
{
int * p = new int;
delete p;
}
Toán Tử delete
14
Vùng nhớ động có thể được trả về bởi hàm
Vùng nhớ động chỉ được giải phóng khi sử
dụng delete, do đó vùng nhớ động tạo ra
trong hàm không bị xóa sau khi kết thúc hàm
Chỉ các biến khai báo trong hàm bị xóa, trong
đó có biến con trỏ p
Giới Thiệu Lập Trình
int * f(int * q) {
int * p = new int;
return p;
}
Mảng Động
15
Biến mảng thực chất là biến con trỏ
Mảng thông thường (int a[10])
Độ dài mảng cố định
Không thể thay đổi độ dài sau khi khai báo
Có thể coi là con trỏ hằng (con trỏ tĩnh)
Mảng động (int * a = new int[10])
Độ dài mảng có thể thay đổi sau khi khai báo
Sử dụng lại toán tử new
int * a = new int[10];
a = new int[50];
Giới Thiệu Lập Trình
Mảng Động – Mảng Tĩnh
16
int * a = new int[10];
int * p;
a và p đều là biến con trỏ, nhưng a là hằng
Có thể gán (được phép)
p = a;
p chỉ tới địa chỉ mà a đang chỉ tới
Nhưng không được phép (lỗi dịch)
a = p;
a là hằng, không thay đổi giá trị của a
Giới Thiệu Lập Trình
Nhắc Lại: cstring & Lớp string
17
char aCString[];
string stringVar;
Chuyển cstring sang string (hợp lệ)
stringVar = aCString;
Chuyển string sang cstring (không hợp lệ)
aCString = stringVar;
Giới Thiệu Lập Trình
Mảng Động
18
Hạn chế của mảng thông thường:
Phải khai báo độ dài trước
Độ dài mảng có thể không biết tới khi chạy
chương trình
Phải ước lượng độ dài lớn nhất
Lãng phí bộ nhớ
Mảng động
Có thể tăng và giảm khi cần thiết
Giới Thiệu Lập Trình
Giải Phóng Mảng Động
19
Cũng được thực hiện khi chạy
d = new double[10];
// thao tác với d
delete [] d;
Giải phóng tất cả bộ nhớ cho mảng động
[] thông báo giải phóng bộ nhớ cho mảng
Vẫn chỉ tới vùng nhớ đó
Nên gán d = NULL;
Giới Thiệu Lập Trình
Bài Tập
20Giới Thiệu Lập Trình
int a[10] = {2,3,5,1,4,7,0};
int *p = a;
cout << a[0] << *p << "\n";
p++;
cout << *p << p[2] << "\n";
p++; a[2] = 0;
cout << p[1] << *p << "\n";
p -= 2;
cout << p[3] << p[1] << "\n";
2 2
3 1
1 9
1 3
Hàm Trả Về Mảng
21
Kiểu mảng không được phép là kiểu trả về
Không hợp lệ
int[] someFunction();
Phải trả về kiểu con trỏ
int * someFunction();
Giới Thiệu Lập Trình
Con Trỏ Trong C++
22
Con trỏ là khối kiến thức đặc biệt quan trọng
trong C++
Phải nắm vững khái niệm con trỏ cũng như
thao tác với con trỏ
Con trỏ sẽ được sử dụng trong các kiểu dữ
liệu phức tạp
INT 2203 Cấu trúc Dữ liệu & Giải thuật
Giới Thiệu Lập Trình
Các file đính kèm theo tài liệu này:
- ts_le_nguyen_khoibaigiang09_contro_8911_2032120.pdf