ตัวอย่างของตำแหน่งที่ตัวชี้ const สามารถใช้งานได้สูง พิจารณาว่าคุณมีคลาสที่มีอาร์เรย์แบบไดนามิกอยู่ภายในและคุณต้องการส่งการเข้าถึงของผู้ใช้ไปยังอาร์เรย์ แต่ไม่ได้ให้สิทธิ์ในการเปลี่ยนพอยน์เตอร์ พิจารณา:
#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());
}
ซึ่งผลิต:
ใส่ข้อมูล
ใส่ข้อมูล
แต่ถ้าเราลองทำสิ่งนี้:
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
}
เราได้รับ:
ข้อผิดพลาด: lvalue จำเป็นต้องเป็น operand ด้านซ้ายของการมอบหมาย // Drat แพ้รู้อีกครั้ง!
เห็นได้ชัดว่าเราสามารถแก้ไขเนื้อหาของอาร์เรย์ได้ แต่ไม่ใช่ตัวชี้ของอาร์เรย์ ดีถ้าคุณต้องการตรวจสอบให้แน่ใจว่าตัวชี้มีสถานะที่สอดคล้องกันเมื่อส่งกลับไปยังผู้ใช้ มีหนึ่งจับแม้ว่า:
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!
}
เรายังสามารถลบการอ้างอิงหน่วยความจำของตัวชี้แม้ว่าเราจะไม่สามารถปรับเปลี่ยนตัวชี้ได้
ดังนั้นหากคุณต้องการให้การอ้างอิงหน่วยความจำชี้ไปที่บางสิ่งบางอย่างเสมอ (ไม่เคยแก้ไข IE เหมือนกับการอ้างอิงในปัจจุบัน) มันก็ใช้ได้ดี หากคุณต้องการให้ผู้ใช้มีสิทธิ์เข้าถึงแบบเต็มและปรับเปลี่ยนผู้ใช้นั้นไม่ใช่ผู้ใช้สำหรับคุณ
แก้ไข:
หลังจากสังเกต okorz001 ความคิดเห็นที่ไม่สามารถกำหนดได้เนื่องจาก GetArray () เป็นตัวถูกดำเนินการค่าความคิดเห็นของเขาถูกต้องทั้งหมด แต่ข้างต้นยังคงใช้ถ้าคุณจะกลับการอ้างอิงไปยังตัวชี้ (ฉันคิดว่าฉันสมมติว่า GetArray คือ อ้างอิงการอ้างอิง) ตัวอย่างเช่น:
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
}
จะกลับมาเป็นครั้งแรกที่ทำให้เกิดข้อผิดพลาด:
ข้อผิดพลาด: การกำหนดตำแหน่งแบบอ่านอย่างเดียว 'Temp.TestA :: GetArray ()'
แต่ครั้งที่สองจะเกิดขึ้นอย่างสนุกสนานแม้จะมีผลกระทบที่อาจเกิดขึ้นภายใต้
เห็นได้ชัดว่าคำถามจะถูกยก 'ทำไมคุณต้องการกลับไปอ้างอิงถึงตัวชี้' มีอินสแตนซ์ที่หายากซึ่งคุณจำเป็นต้องกำหนดหน่วยความจำ (หรือข้อมูล) ให้กับตัวชี้ดั้งเดิมที่เป็นปัญหาโดยตรง (ตัวอย่างเช่นการสร้าง malloc / free หรือ new / free front-end) ของคุณเอง แต่ในกรณีเหล่านั้นเป็นการอ้างอิงที่ไม่ใช่แบบ const . การอ้างอิงถึงตัวชี้ const ฉันไม่เจอสถานการณ์ที่จะรับประกันได้ (เว้นแต่ว่าอาจจะเป็นตัวแปรอ้างอิง const ที่ประกาศไว้แทนที่จะเป็นประเภทการส่งคืนหรือไม่)
พิจารณาว่าเรามีฟังก์ชั่นที่ใช้ตัวชี้ const (หรืออันที่ไม่ใช่):
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");
}
ข้อผิดพลาดใน const สร้างข้อความดังนั้น:
ข้อผิดพลาด: การลดลงของพารามิเตอร์แบบอ่านอย่างเดียว 'ข้อมูล'
ซึ่งเป็นสิ่งที่ดีเพราะเราอาจไม่ต้องการทำเช่นนั้นเว้นแต่ว่าเราต้องการทำให้เกิดปัญหาในการแสดงความคิดเห็น หากเราแก้ไขการลดลงของฟังก์ชัน const จะเกิดสิ่งต่อไปนี้:
NonConst: A
Const: B
เห็นได้ชัดแม้ว่า A คือ 'Data [1]' มันจะถูกใช้เป็น 'Data [0]' เพราะตัวชี้ NonConst อนุญาตการดำเนินการลดลง เมื่อ const ดำเนินการตามที่คนอื่นเขียนเราจับข้อบกพร่องที่อาจเกิดขึ้นก่อนที่มันจะเกิดขึ้น
ข้อพิจารณาหลักอีกข้อหนึ่งคือตัวชี้ const สามารถใช้เป็นการอ้างอิงแบบหลอกในสิ่งที่จุดอ้างอิงไม่สามารถเปลี่ยนแปลงได้ (สิ่งมหัศจรรย์หนึ่งอย่างถ้าเป็นไปได้ พิจารณา:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
เมื่อพยายามรวบรวมให้สร้างข้อผิดพลาดต่อไปนี้:
ข้อผิดพลาด: การกำหนดตัวแปรแบบอ่านอย่างเดียว 'B'
ซึ่งน่าจะเป็นสิ่งที่ไม่ดีหากต้องการอ้างอิงอย่างต่อเนื่องกับ A ถ้าB = NULL
ถูกคอมเม้นท์คอมไพเลอร์จะให้เราแก้ไขอย่างมีความสุข*B
และดังนั้น A. สิ่งนี้อาจดูเหมือนไม่เป็นประโยชน์กับ ints แต่ให้พิจารณาว่าคุณมีจุดยืนเดียวของแอปพลิเคชั่นกราฟิกที่คุณต้องการตัวชี้ที่ไม่สามารถแก้ไขได้ รอบ
มันใช้เป็นตัวแปร (แก้ตัวโดยไม่ตั้งใจปุน) แต่ใช้อย่างถูกต้องมันเป็นเครื่องมืออื่นในกล่องเพื่อช่วยในการเขียนโปรแกรม