ในทั้งสองกรณีเนื่องจากคุณจับโดยการอ้างอิงคุณจึงสามารถปรับเปลี่ยนสถานะของออบเจ็กต์ข้อยกเว้นดั้งเดิมได้อย่างมีประสิทธิภาพ (ซึ่งคุณสามารถคิดได้ว่าอาศัยอยู่ในตำแหน่งหน่วยความจำที่มีมนต์ขลังซึ่งจะยังคงใช้ได้ในระหว่างการคลี่คลาย0x98e7058
ในภายหลัง - ในตัวอย่างด้านล่าง) อย่างไรก็ตาม
- ในกรณีแรกเนื่องจากคุณสร้างใหม่ด้วย
throw;
(ซึ่งแตกต่างจากการthrow err;
รักษาวัตถุข้อยกเว้นดั้งเดิมด้วยการปรับเปลี่ยนของคุณใน "สถานที่วิเศษ" ที่กล่าวว่า0x98e7058
) จะแสดงถึงการเรียกให้ผนวก ()
- ในกรณีที่สองเนื่องจากคุณโยนบางสิ่งอย่างโจ่งแจ้งสำเนาของ
err
จะถูกสร้างขึ้นแล้วโยนใหม่ (ที่ "สถานที่วิเศษ" ที่แตกต่างกัน0x98e70b0
- เพราะสำหรับคอมไพเลอร์ทั้งหมดรู้ว่าerr
อาจเป็นวัตถุบนสแต็กที่กำลังจะคลายออกเช่นe
เดิม ที่0xbfbce430
ไม่ใช่ใน "สถานที่วิเศษ" ที่0x98e7058
) ดังนั้นคุณจะสูญเสียข้อมูลเฉพาะคลาสที่ได้รับระหว่างการสร้างสำเนาของอินสแตนซ์คลาสพื้นฐาน
โปรแกรมง่ายๆเพื่อแสดงสิ่งที่เกิดขึ้น:
#include <stdio.h>
struct MyErr {
MyErr() {
printf(" Base default constructor, this=%p\n", this);
}
MyErr(const MyErr& other) {
printf(" Base copy-constructor, this=%p from that=%p\n", this, &other);
}
virtual ~MyErr() {
printf(" Base destructor, this=%p\n", this);
}
};
struct MyErrDerived : public MyErr {
MyErrDerived() {
printf(" Derived default constructor, this=%p\n", this);
}
MyErrDerived(const MyErrDerived& other) {
printf(" Derived copy-constructor, this=%p from that=%p\n", this, &other);
}
virtual ~MyErrDerived() {
printf(" Derived destructor, this=%p\n", this);
}
};
int main() {
try {
try {
MyErrDerived e;
throw e;
} catch (MyErr& err) {
printf("A Inner catch, &err=%p\n", &err);
throw;
}
} catch (MyErr& err) {
printf("A Outer catch, &err=%p\n", &err);
}
printf("---\n");
try {
try {
MyErrDerived e;
throw e;
} catch (MyErr& err) {
printf("B Inner catch, &err=%p\n", &err);
throw err;
}
} catch (MyErr& err) {
printf("B Outer catch, &err=%p\n", &err);
}
return 0;
}
ผลลัพธ์:
Base default constructor, this=0xbfbce430
Derived default constructor, this=0xbfbce430
Base default constructor, this=0x98e7058
Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
Derived destructor, this=0xbfbce430
Base destructor, this=0xbfbce430
A Inner catch, &err=0x98e7058
A Outer catch, &err=0x98e7058
Derived destructor, this=0x98e7058
Base destructor, this=0x98e7058
---
Base default constructor, this=0xbfbce430
Derived default constructor, this=0xbfbce430
Base default constructor, this=0x98e7058
Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
Derived destructor, this=0xbfbce430
Base destructor, this=0xbfbce430
B Inner catch, &err=0x98e7058
Base copy-constructor, this=0x98e70b0 from that=0x98e7058
Derived destructor, this=0x98e7058
Base destructor, this=0x98e7058
B Outer catch, &err=0x98e70b0
Base destructor, this=0x98e70b0
ดูเพิ่มเติมที่: