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
em thấy có dòng này hơi lạ lạ nên chắc code 1 không chạy :v
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ó.
Không có đoạn chương trình nào ở trên chạy đc cả
Nhờ anh giải thích với ạ
hay quá lúc đầu e ko để ý đến vòng for(), sơ xuất quá