Một ví dụ về nơi một con trỏ const có khả năng áp dụng cao có thể được chứng minh như vậy. Hãy xem xét bạn có một lớp với một mảng động bên trong nó và bạn muốn chuyển quyền truy cập của người dùng vào mảng nhưng không cấp cho họ quyền thay đổi con trỏ. Xem xét:
#include <new>
#include <string.h>
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const GetArray(){ return Array; }
};
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
}
Sản xuất:
Dữ liệu đầu vào
đặt dữ liệu
Nhưng nếu chúng ta thử điều này:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
Chúng tôi nhận được:
lỗi: lvalue được yêu cầu như toán hạng bên trái của phép gán // Drat bị lỗi lần nữa!
Vì vậy, rõ ràng chúng ta có thể sửa đổi nội dung của mảng, nhưng không phải con trỏ của mảng. Tốt nếu bạn muốn đảm bảo con trỏ có trạng thái nhất quán khi chuyển nó lại cho người dùng. Có một nhược điểm, mặc dù:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
Chúng ta vẫn có thể xóa tham chiếu bộ nhớ của con trỏ, ngay cả khi chúng ta không thể sửa đổi chính con trỏ.
Vì vậy, nếu bạn muốn tham chiếu bộ nhớ luôn luôn trỏ đến một cái gì đó (IE không bao giờ được sửa đổi, tương tự như cách một tham chiếu hiện đang hoạt động), thì nó rất có thể áp dụng. Nếu bạn muốn người dùng có quyền truy cập đầy đủ và sửa đổi nó, thì non-const là dành cho bạn.
Biên tập:
Sau khi nhận thấy okorz001 nhận xét về việc không thể gán do GetArray () là toán hạng giá trị đúng, nhận xét của anh ta hoàn toàn chính xác, nhưng ở trên vẫn áp dụng nếu bạn trả về một tham chiếu cho con trỏ (tôi cho rằng tôi cho rằng GetArray là tham chiếu một tài liệu tham khảo), ví dụ:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; } //Note & reference operator
char * &GetNonConstArray(){ return Array; } //Note non-const
};
int main()
{
TestA Temp;
Temp.GetArray() = NULL; //Returns error
Temp.GetNonConstArray() = NULL; //Returns no error
}
Sẽ trở lại trong lần đầu tiên dẫn đến một lỗi:
lỗi: gán vị trí chỉ đọc 'Temp.TestA :: GetArray ()'
Nhưng lần thứ hai sẽ xảy ra vui vẻ bất chấp hậu quả tiềm ẩn ở bên dưới.
Rõ ràng, câu hỏi sẽ được đặt ra 'tại sao bạn muốn trả lại một tham chiếu cho một con trỏ'? Có những trường hợp hiếm hoi mà bạn cần gán bộ nhớ (hoặc dữ liệu) trực tiếp cho con trỏ ban đầu được đề cập (ví dụ: xây dựng malloc / free hoặc new / free front-end của riêng bạn), nhưng trong những trường hợp đó, nó là một tham chiếu không phải là const . Tham chiếu đến một con trỏ const Tôi không gặp phải tình huống sẽ bảo đảm nó (trừ khi có thể là các biến tham chiếu const được khai báo thay vì các kiểu trả về?).
Hãy xem xét nếu chúng ta có một hàm lấy một con trỏ const (so với một hàm không):
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; }
void ModifyArrayConst(char * const Data)
{
Data[1]; //This is okay, this refers to Data[1]
Data--; //Produces an error. Don't want to Decrement that.
printf("Const: %c\n",Data[1]);
}
void ModifyArrayNonConst(char * Data)
{
Data--; //Argh noo what are you doing?!
Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
printf("NonConst: %c\n",Data[1]);
}
};
int main()
{
TestA Temp;
Temp.ModifyArrayNonConst("ABCD");
Temp.ModifyArrayConst("ABCD");
}
Các lỗi trong const tạo ra thông báo như vậy:
lỗi: giảm tham số chỉ đọc 'Dữ liệu'
Điều này là tốt vì có lẽ chúng ta không muốn làm điều đó, trừ khi chúng ta muốn gây ra các vấn đề được biểu thị trong các bình luận. Nếu chúng ta chỉnh sửa phần giảm trong hàm const, điều sau đây xảy ra:
NonConst: A
Const: B
Rõ ràng, mặc dù A là 'Dữ liệu [1]', nhưng nó được coi là 'Dữ liệu [0]' vì con trỏ NonConst cho phép hoạt động giảm dần. Với const được triển khai, như một người khác viết, chúng tôi bắt được lỗi tiềm ẩn trước khi nó xảy ra.
Một cân nhắc chính khác, đó là một con trỏ const có thể được sử dụng làm tham chiếu giả, trong đó điều mà các điểm tham chiếu không thể thay đổi (người ta tự hỏi, nếu có lẽ đây là cách nó được thực hiện). Xem xét:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
Khi cố gắng biên dịch, tạo ra lỗi sau:
lỗi: gán biến chỉ đọc 'B'
Đó có lẽ là một điều xấu nếu muốn tham chiếu liên tục đến A. Nếu B = NULL
được nhận xét, trình biên dịch sẽ vui lòng cho chúng tôi sửa đổi *B
và do đó A. Điều này có vẻ không hữu ích với ints, nhưng hãy xem xét nếu bạn có một lập trường duy nhất của một ứng dụng đồ họa trong đó bạn muốn một con trỏ không thể thay đổi được đề cập đến mà bạn có thể vượt qua xung quanh.
Cách sử dụng của nó là khác nhau (xin lỗi vì chơi chữ ngoài ý muốn), nhưng được sử dụng một cách chính xác, nó là một công cụ khác trong hộp để hỗ trợ lập trình.