- from alpha to omega 4 Trả về giá trị của hàm (returning value from functions)
6. Con trỏ và hằng (pointers and constants)
C++ cung cấp khái niệm hằng (const) để thể hiện rằng đối tượng nào đó là cố định, không thể thay đổi được. Điều này có những lợi ích nhất định tùy thuộc vào ngữ cảnh. Ví dụ: bằng việc khai báo hằng tượng trưng (symbolic constant) sẽ giúp việc viết chương trình được thuận lợi và dễ bảo trì hơn là việc “nhúng” hẳn các hằng trực tiếp vào trong code. Ví dụ: C++ Code:
Lựa chọn code | Ẩn/Hiện code
const int PI=3.14; // như thế này tốt hơn là nhúng hẳn số 3.14 và từng đoạn code
Hoặc ví dụ trong một số trường hợp, khi ta truyền biến bằng tham chiếu cho hàm nhưng chỉ cho phép hàm đọc dữ liệu mà không cho phép chỉnh sửa dữ liệu thì tham số hình thức của hàm sẽ được khai báo là tham chiếu hằng hoặc con trỏ hằng. Sau đây là một số ví dụ khai báo hằng:
C++ Code:
Lựa chọn code | Ẩn/Hiện code
const int x=12; // x là hằng nguyên, giá trị 12
const char ch[]={‘I’, ‘H’, ‘A’, ‘T’, ‘E’, ‘U’}; // ch là con trỏ hằng (const pointer) trỏ tới phần tử đầu mảng
const int number; // Error: phải khởi tạo hằng ngay khi khai báo
Khi sử dụng con trỏ có hai đối tượng cần quan tâm: thứ nhất là bản thân con trỏ và thứ hai là đối tượng mà con trỏ trỏ tới. Ta phân biệt hai khái niệm: con trỏ hằng(const pointer, một số người thì gọi là hằng con trỏ, cái này tùy thuộc vào cách dịch) và con trỏ tới hằng (pointer to const).
Con trỏ hằng (const pointer): là con trỏ luôn luôn trỏ tới một địa chỉ cố định, và không
thể thay đổi được trong suốt thời gian thực thi chương trình. Mọi nỗ lực sử đổi như gán địa chỉ mới cho con trỏ hằng hay tăng giảm con trỏ hằng đều gây lỗi biên dịch. Ví dụ quen thuộc nhất về con trỏ hằng là tên mảng:
C++ Code:
Lựa chọn code | Ẩn/Hiện code
// tên mảng là một const pointer
char str[]=”I am first_pace, from congdongCViet”; // str là con trỏ hằng, nhưng các str[i] không phải hằng
char* p1;
char* p2;
p1=str; // ok: vì p1 không phải con trỏ hằng nên được phép trỏ đi chỗ khác
str=p2; // error: vì str là con trỏ hằng nên không thể trỏ đi chỗ khác được
Con trỏ tới hằng (pointer to const): là con trỏ trỏ tới một đối tượng hằng, tức là với con
trỏ đó, đối tượng được "hiểu" là hằng. Con trỏ này có thể đọc (read) dữ liệu của đối tượng nhưng không được sửa đổi (write) nội dung của đối tượng. Mọi nỗ lực sửa đổi nội dung của đối tượng sẽ gây ra lỗi biên dịch. Con trỏ tới hằng khác con trỏ hằng ở hai điểm: thứ
nhất, khi không thích trỏ tới đối tượng này nó có thể trỏ tới đối tượng khác, con trỏ hằng không được phép làm điều này. Thứ hai, con trỏ tới đối tượng hằng (pointer to constant) thì nó hiểu đối tượng là hằng, và không được phép “ghi” dữ liệu lên đối tượng, còn con trỏ hằng nó vẫn cho phép thao tác trên dữ liệu, nó hoàn toàn giống con trỏ bình thường ngoài việc nó chỉ trỏ tới một địa chỉ cố định.
Khi ta đặt từ khóa const trước một khai báo con trỏ thông thường thì điều đó khiến con trỏ “hiểu” đối tượng là hằng chứ không phải con trỏ là hằng. Nghĩa là nó chỉ có
thể “đọc” dữ liệu từ đối tượng nhưng không thể “ghi” dữ liệu lên đối tượng. Trong trường hợp này nó là con trỏ đến đối tượng hằng (pointer to const). Tuy nhiênđối tượng không phải là trở thành hằng, mà nó chỉ được con trỏ đó “hiểu là hằng” (chỉ là là hằng đối với con trỏ đó), đối với con trỏ khác nó có thể là biến. Để hiểu rõ hơn ta xem xét ví dụ sau: C++ Code:
Lựa chọn code | Ẩn/Hiện code
char str[]="Hello, Ajinomoto"; // str là con trỏ hằng, nhưng str[i] thì không
const char* p=str; // con trỏ p (pointer to const) trỏ đến đầu mảng str, và p “hiểu” str[i] là các hằng
p[3]='X'; // Error: không được, vì p chỉ được đọc dữ liệu chứ không được ghi dữ liệu lên str[i]
str[3]='X'; // Ok: vì str[i] chỉ được coi là hằng theo “cách hiểu” của p, với str thì các str[i] vẫn là biến
Để khai báo một con trỏ hằng ta phải sử dụng *const chứ không phải const. Xem xét ví dụ sau:
C++ Code:
Lựa chọn code | Ẩn/Hiện code
int x, y;
int *const px=&x; // bây giờ px luôn luôn trỏ đến x, không thể thay đổi được
px=&y; // Error: px là con trỏ hằng, không được phép trỏ đi chỗ khác
Có thể tóm lại như trong ví dụ sau: C++ Code:
Lựa chọn code | Ẩn/Hiện code
const int* p1=&x; // con trỏ tới hằng int (pointer to const char)
int const* p2=&x; // hoàn toàn giống p1, con trỏ tới hằng int (pointer to const char)
int *const p3=&x; // con trỏ hằng tới biến char (pointer to const char)
Để dễ nhớ các bạn có thể đọc từ trái sang phải như sau: “p3 là con trỏ hằng tới kiểu int”.
Chú ý: một đối tượng hằng là cố định, vì vậy gán địa chỉ của nó cho một “con trỏ tự do” sẽ
gây lỗi biên dịch. Bởi vì thông qua con trỏ ta có thể thay đổi giá trị của hằng, và điều này là không được phép. C++ chỉ cho phép gán địa chỉ của một đối tượng hằng cho một con trỏ trỏ tới đối tượng hằng (pointer to const). Ví dụ chương trình sau:
C++ Code:
Lựa chọn code | Ẩn/Hiện code
const int* p1=&x; // Ok: con trỏ p1 trỏ tới hằng x
int* p2=&x; // Error: con trỏ p2 là “con trỏ tự do”, không được phép trỏ tới
hằng x
Câu hỏi mở rộng nhé: việc gán địa chỉ của một đối tượng hằng cho con trỏ hằng (const
pointer) là có được phép hay không? Tại sao? Nhưng từ từ hãy post vội, đợi mình viết nốt loạt tut này đã
Hết bài 10b
__________________
Vấn đề không phải là bước nhanh, mà là luôn luôn bước luôn bước
Đã được chỉnh sửa lần cuối bởi first_pace : 20-03-2011 lúc 11:53 PM.
#16 07-03-2011, 10:26 PM 07-03-2011, 10:26 PM first_pace Thành viên chính thức Ngày gia nhập: 02 2011 Nơi ở: Hà Nội Bài viết: 67 Mảng (array) trong C++ BÀI 11. MẢNG - ARRAY
Trong C++, mảng là một nhóm các vùng nhớ liên tiếp có cùng kiểu dữ liệu. Thông thường mảng chứa những phần tử dữ liệu có liên quan đến nhau. Mảng có thể là một chiều, hai
chiều, hoặc nhiều hơn hai chiều, trong đó mảng 1 chiều là thông dụng nhất.