วันนี้เราพบสาเหตุของข้อผิดพลาดที่น่ารังเกียจที่เกิดขึ้นเป็นระยะ ๆ ในบางแพลตฟอร์มเท่านั้น ต้มโค้ดของเราออกมาเป็นแบบนี้:
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
ซึ่งจะลบรายการแผนที่ก่อนที่จะพยายามพิมพ์ (ในกรณีของเรามันก็ไม่ได้พิมพ์ แต่ใช้ในทางที่ซับซ้อนมากขึ้น) นี้เป็นหลักสูตรที่ไม่ได้กำหนดพฤติกรรมเนื่องจากมีการอ้างอิงห้อยหลังจากการเรียกร้องให้key
erase
แก้ไขครั้งนี้เป็นที่น่ารำคาญ - เราเพิ่งเปลี่ยนประเภทพารามิเตอร์จากไปconst string&
string
คำถามคือเราจะหลีกเลี่ยงข้อผิดพลาดนี้ได้ตั้งแต่แรกอย่างไร? ดูเหมือนว่าทั้งสองฟังก์ชั่นทำในสิ่งที่ถูกต้อง:
A
ไม่มีทางรู้ว่าkey
หมายถึงสิ่งที่มันกำลังจะทำลายB
สามารถทำสำเนาก่อนส่งให้A
แต่เป็นหน้าที่ของผู้ตัดสินใจว่าจะรับพารามิเตอร์ตามมูลค่าหรือโดยอ้างอิงหรือไม่
มีกฎบางอย่างที่เราไม่สามารถทำตามได้หรือไม่?