30/09/2018, 22:44

Con trỏ và hằng

Chào các bạn đang theo dõi khóa học lập trình trực tuyến ngôn ngữ C++.

Trong các bài học có liên quan đến con trỏ trước đây, chúng ta đã biết con trỏ cũng là một biến thông thường mà giá trị nó có thể chứa là địa chỉ của vùng nhớ khác. Như vậy, từ khóa const cũng có thể được sử dụng cho con trỏ như các biến có kiểu dữ liệu khác. Tuy nhiên, tùy vào vị trí đặt từ khóa const khi khai báo con trỏ mà nó lại có những ý nghĩa khác nhau.

Pointer to const

Thử xem xét ví dụ sau:

int value = 5;
int *ptr = &value;
*ptr = 10; //change value to 10

Với đoạn code này, chương trình của chúng ta hoạt động bình thường. Nó đơn thuần chỉ là dùng một con trỏ có tên ptr trỏ đến địa chỉ của biến value. Bây giờ chúng ta có một chút thay đổi như sau:

const int value = 5;
int *ptr = &value; //compile error

Trong đoạn code trên, mình đã đặt vùng nhớ tại địa chỉ của biến value là vùng nhớ hằng, điều đó có nghĩa giá trị bên trong vùng nhớ đó không thể bị thay đổi. Mặc dù chúng ta chỉ mới cho con trỏ ptr trỏ đến vùng nhớ hằng đó chứ chưa thực hiện câu lệnh nào liên quan đến việc thay đổi giá trị bên trong vùng nhớ của biến value, nhưng compiler ngăn chặn điều này để đảm bảo an toàn dữ liệu cho vùng nhớ của biến value.

Như vậy, công cụ con trỏ thông thường không được phép sử dụng để trỏ đến vùng nhớ hằng, chúng ta cần sử dụng công cụ khác, có thể gọi là Pointer to const (Con trỏ dùng để trỏ đến hằng). Để có một Pointer to const, chúng ta chỉ cần thêm từ khóa const đứng trước kiểu dữ liệu của con trỏ.

const int value = 5;
const int *ptr = &value; //it's ok, ptr point to a "const int"
*ptr = 10; //compile error

Lúc này, con trỏ ptr trở thành Pointer to const nên nó đã có thể trỏ đến vùng nhớ hằng. Tuy nhiên, con trỏ này cũng không thể thay đổi giá trị bên trong vùng nhớ hằng. Do đó, compiler thông báo lỗi “cannot assign to a variable that is const”.

Một Pointer to const dùng để trỏ đến một vùng nhớ hằng, nó cũng có thể trỏ đến một vùng nhớ không phải hằng. Ví dụ:

int value = 5;
const int *ptr = &value;
*ptr = 10; //compile error

Mặc dù Pointer to const có thể trỏ đến vùng nhớ không phải hằng, nhưng nó lại không thể thay đổi giá trị bên trong vùng nhớ đó. Nếu biên dịch đoạn code trên, compiler sẽ thông báo lỗi “assignment of read-only location ‘* ptr’”. Điều này có nghĩa Pointer to const là loại con trỏ chỉ có chức năng đọc nội dung của vùng nhớ (bất kể vùng nhớ đó có phải hằng hay không) chứ không có chức năng ghi giá trị vào vùng nhớ.

Do đó, sử dụng Pointer to const sẽ đảm bảo toàn vẹn dữ liệu cho vùng nhớ mà nó trỏ đến.

Điểm đáng chú ý ở Pointer to const là một Pointer to const không phải là một biến hằng, nó chỉ là một loại công cụ có chức năng read-only. Do đó, chúng ta vẫn có thể cho Pointer to const trỏ đến vùng nhớ khác sau khi khởi tạo.

const int *ptr = NULL;

int value1 = 5;
ptr = &value1;

int value2 = 10;
ptr = &value2;

Chúng ta có thể khai báo Pointer to const bằng cách đặt từ khóa const như sau:

int const *ptr = NULL;

Nhưng đây là cách khai báo dễ nhầm lẫn nên mình vẫn thích dùng cách cũ hơn:

const int *ptr = NULL;
Const pointer

Const pointer là loại con trỏ chỉ gán được địa chỉ một lần khi khởi tạo, điều này có nghĩa sau khi trỏ đến vùng nhớ nào đó thì nó không thể trỏ đi nơi khác được. Để khai báo const pointer, chúng ta cần đặt từ khóa con giữa dấu * và tên con trỏ.

int value = 5;
int *const ptr = &value;

Cũng giống như const variable, const pointer cần được khởi tạo ngay sau khi khai báo, và địa chỉ được gán cho const pointer sẽ không thể thay đổi về sau.

int value1 = 5;
int value2 = 10;
int *const ptr = &value1;
ptr = &value2; //compile error

Xét lại đoạn chương trình này:

int value = 5;
int *const ptr = &value;

Lúc này, con trỏ ptr chính nó là hằng, nhưng vùng nhớ mà nó trỏ đến (biến value) lại không phải hằng, nên con trỏ ptr hoàn toàn có thể thay đổi giá trị của biến value.

int value = 5;
int *const ptr = &value;
*ptr = 10; //it's ok, change value of non-const memory area

Như vậy, const pointer có đầy đủ chức năng đọc và ghi giá trị lên vùng nhớ.

Const pointer to const

Chúng ta hoàn toàn có thể kết hợp cả 2 loại con trỏ trên lại với nhau để tạo thành loại con trỏ mới gọi là const pointer to const. Loại con trỏ này sẽ có chức năng read-only, và nó cũng không thể trỏ đến vùng nhớ khác sau khi đã khởi tạo.

int value = 5;
const int *const ptr = &value;

&ptr = 10; //compile error

int otherValue = 10;
ptr = &otherValue; //compile error

Tổng kết

Trong bài học này, chúng ta đã được biết thêm một số khái niệm về con trỏ có liên quan đến hằng. Khi sử dụng từ khóa const, chúng ta có thể tạo ra 2 loại con trỏ tùy vào vị trí đặt từ khóa const. Pointer to const là loại con trỏ chỉ có chức năng đọc nội dung vùng nhớ mà nó trỏ đến. Const pointer cũng tương tự như một biến hằng thông thường, vì giá trị mà nó nắm giữ là địa chỉ và nó là hằng, nên địa chỉ của con trỏ này sẽ không bị thay đổi (không thể trỏ đến vùng nhớ khác sau khi khởi tạo).

Bài tập cơ bản

Trong số các đoạn code dưới đây, đoạn code nào có thể biên dịch được?

Code 1:

#include <iostream>
#include <cstring>
using namespace std;

int main() {

	char str[] = "Le Tran Dat";
	char *const p_str = str;
	
	for(int i = 0; i < strlen(str); p_str++)
	{
		*p_str = ' ';
	}
	
	cout << p_str << endl;

	return 0;
}

Code 2:

#include <iostream>
#include <cstring>
using namespace std;

int main() {

	char str[] = "Le Tran Dat";
	const char *p_str = str;
	
	for(int i = 0; i < strlen(str); i++)
	{
		*(p_str + i) = ' ';
	}
	
	cout << p_str << endl;

	return 0;
}

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.

www.daynhauhoc.com


Link Videos khóa học

https://www.udemy.com/c-co-ban-danh-cho-nguoi-moi-hoc-lap-trinh/learn/v4/overview

Nguyễn Hoàng Trung viết 00:46 ngày 01/10/2018

char *const p_str = str;

em thấy có dòng này hơi lạ lạ nên chắc code 1 không chạy :v

kiencon viết 00:53 ngày 01/10/2018

a nghĩ dòng này bình thường mà, nó chỉ khởi tạo 1 con trỏ hằng và gán địa chỉ của con trỏ str cho nó.

... viết 00:54 ngày 01/10/2018

Không có đoạn chương trình nào ở trên chạy đc cả

Nguyễn Hoàng Trung viết 00:56 ngày 01/10/2018

Nhờ anh giải thích với ạ

ldt amfisbitophobia viết 00:49 ngày 01/10/2018

Dùng Const pointer, nhưng trong vòng for lại thay đổi địa chỉ mà con trỏ trỏ đến.

hay quá lúc đầu e ko để ý đến vòng for(), sơ xuất quá

Bài liên quan
0