วันนี้เราพบสาเหตุของข้อผิดพลาดที่น่ารังเกียจที่เกิดขึ้นเป็นระยะ ๆ ในบางแพลตฟอร์มเท่านั้น ต้มโค้ดของเราออกมาเป็นแบบนี้:
class Foo {
map<string,string> m;
void A(const string& key) {
m.erase(key);
cout << "Erased: " << key; // oops
}
void B() {
while (!m.empty()) {
auto toDelete = m.begin();
A(toDelete->first);
}
}
}
ปัญหาอาจดูเหมือนชัดเจนในกรณีที่ง่ายนี้: Bผ่านการอ้างอิงถึงคีย์Aซึ่งจะลบรายการแผนที่ก่อนที่จะพยายามพิมพ์ (ในกรณีของเรามันก็ไม่ได้พิมพ์ แต่ใช้ในทางที่ซับซ้อนมากขึ้น) นี้เป็นหลักสูตรที่ไม่ได้กำหนดพฤติกรรมเนื่องจากมีการอ้างอิงห้อยหลังจากการเรียกร้องให้keyerase
แก้ไขครั้งนี้เป็นที่น่ารำคาญ - เราเพิ่งเปลี่ยนประเภทพารามิเตอร์จากไปconst string& stringคำถามคือเราจะหลีกเลี่ยงข้อผิดพลาดนี้ได้ตั้งแต่แรกอย่างไร? ดูเหมือนว่าทั้งสองฟังก์ชั่นทำในสิ่งที่ถูกต้อง:
Aไม่มีทางรู้ว่าkeyหมายถึงสิ่งที่มันกำลังจะทำลายBสามารถทำสำเนาก่อนส่งให้Aแต่เป็นหน้าที่ของผู้ตัดสินใจว่าจะรับพารามิเตอร์ตามมูลค่าหรือโดยอ้างอิงหรือไม่
มีกฎบางอย่างที่เราไม่สามารถทำตามได้หรือไม่?