Dalam kedua kasus, karena Anda menangkap dengan referensi, Anda secara efektif mengubah status objek pengecualian asli (yang dapat Anda anggap sebagai berada di lokasi memori ajaib yang akan tetap valid selama pembatalan berikutnya - 0x98e7058
dalam contoh di bawah). Namun,
- Dalam kasus pertama, karena Anda menelusuri ulang
throw;
(yang, tidak seperti throw err;
, mempertahankan objek pengecualian asli, dengan modifikasi Anda, dalam kata "lokasi magis" di 0x98e7058
) akan mencerminkan panggilan ke append ()
- Dalam kasus kedua, karena Anda membuang sesuatu secara eksplisit, salinan dari
err
akan dibuat kemudian dilemparkan lagi (di "lokasi magis" yang berbeda 0x98e70b0
- karena semua yang diketahui oleh kompilator err
dapat menjadi objek di tumpukan yang akan dilepas, seperti e
sebelumnya di 0xbfbce430
, bukan di "lokasi magis" di 0x98e7058
), jadi Anda akan kehilangan data khusus kelas turunan selama pembuatan salinan instance kelas dasar.
Program sederhana untuk menggambarkan apa yang terjadi:
#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;
}
Hasil:
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
Lihat juga: