พยายามรวบรวมการใช้งานบางอย่าง:
เชื่อมโยงบางส่วนกับการอ้างอิงถึง const ชั่วคราวเพื่อยืดอายุการใช้งาน การอ้างอิงสามารถเป็นฐาน - และตัวทำลายของมันไม่จำเป็นต้องเป็นเสมือน - ตัวทำลายที่ถูกต้องยังคงถูกเรียกว่า:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
คำอธิบายโดยใช้รหัส:
struct ScopeGuard {
~ScopeGuard() { } // not virtual
};
template<typename T> struct Derived : ScopeGuard {
T t;
Derived(T t):t(t) { }
~Derived() {
t(); // call function
}
};
template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }
เคล็ดลับนี้ใช้ในคลาสยูทิลิตี้ ScopeGuard ของ Alexandrescu เมื่อชั่วคราวออกไปนอกขอบเขตตัวทำลายของ Derived จะถูกเรียกอย่างถูกต้อง รหัสด้านบนขาดรายละเอียดเล็ก ๆ น้อย ๆ แต่นั่นเป็นเรื่องใหญ่สำหรับมัน
ใช้ const เพื่อบอกวิธีการอื่น ๆ จะไม่เปลี่ยนสถานะตรรกะของวัตถุนี้
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
ใช้ const สำหรับคลาส copy-on-writeเพื่อให้คอมไพเลอร์ช่วยให้คุณตัดสินใจได้ว่าคุณไม่จำเป็นต้องคัดลอกเมื่อใดและเมื่อใด
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
คำอธิบาย : คุณอาจต้องการแบ่งปันข้อมูลเมื่อคุณคัดลอกบางสิ่งตราบเท่าที่ข้อมูลของวัตถุเดิมและวัตถุของสำเนายังคงเหมือนเดิม เมื่อหนึ่งในออบเจ็กต์เปลี่ยนแปลงข้อมูล แต่ตอนนี้คุณต้องมีสองเวอร์ชัน: เวอร์ชันหนึ่งสำหรับต้นฉบับและอีกเวอร์ชันหนึ่งสำหรับสำเนา นั่นคือคุณคัดลอกการเขียนไปยังออบเจ็กต์ใดวัตถุหนึ่งเพื่อให้ทั้งคู่มีเวอร์ชันของตัวเอง
การใช้รหัส :
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
ข้อมูลข้างต้นจะพิมพ์ที่อยู่เดียวกันใน GCC ของฉันเพราะที่ใช้ภาษา C ++ std::string
ดำเนินห้องสมุดเขียนคัดลอกเมื่อ สตริงทั้งสองแม้ว่าจะเป็นอ็อบเจ็กต์ที่แตกต่างกัน แต่ก็ใช้หน่วยความจำเดียวกันสำหรับข้อมูลสตริง การสร้างb
non-const จะชอบเวอร์ชันที่ไม่ใช่ const operator[]
และ GCC จะสร้างสำเนาของบัฟเฟอร์หน่วยความจำสำรองเนื่องจากเราสามารถเปลี่ยนแปลงได้และจะต้องไม่ส่งผลต่อข้อมูลของa
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
สำหรับตัวสร้างการคัดลอกเพื่อทำสำเนาจากวัตถุ const และจังหวะ :
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
สำหรับการสร้างค่าคงที่ที่ไม่สามารถเปลี่ยนแปลงได้เล็กน้อย
double const PI = 3.1415;
สำหรับการส่งผ่านวัตถุโดยพลการโดยการอ้างอิงแทนที่จะเป็นมูลค่า - เพื่อป้องกันการส่งผ่านตามมูลค่าที่อาจมีราคาแพงหรือเป็นไปไม่ได้
void PrintIt(Object const& obj) {
// ...
}