引发异常时, 编译器总是创建一个临时拷贝...

引发异常时, 编译器总是创建一个临时拷贝, 即使异常规范和 catch 块中指定的是引用.

备注: 指定引用的目的并不是避免创建拷贝以提高效率, 而是基类引用可以执行派生类对象.

// Code #include <iostream> class MyException { public: MyException() { ++nCnt; nObjId = nCnt; std::cout << "<+" << nObjId << "> MyException default constructor has been invoked. " << std::endl; } MyException(const MyException& /* rhs */) // Comment 'rhs' to avoid warning C4100. { ++nCnt; nObjId = nCnt; std::cout << "<+" << nObjId << "> MyException copy constructor has been invoked. " << std::endl; } virtual ~MyException() { std::cout << "<-" << nObjId << "> MyException destructor has been invoked. " << std::endl; --nCnt; nObjId = -100000; // Set object id invalid. } int ObjId() { return nObjId; } private: static int nCnt; int nObjId; }; /* static */ int MyException::nCnt = 0; // Cannot use 'static' here! int main() { try { MyException me; throw me; } catch (MyException& me) { std::cout << "<" << me.ObjId() << "> The exception has been caught. " << std::endl; std::cout << "____A____" << std::endl; } std::cout << "____B____" << std::endl; std::cout << std::endl; try { MyException me; throw me; } catch (MyException me) { std::cout << "<" << me.ObjId() << "> The exception has been caught. " << std::endl; std::cout << "____A____" << std::endl; } std::cout << "____B____" << std::endl; std::cout << std::endl; try { MyException me; std::cout << "In try-block, address of me is 0x" << &me << std::endl; throw &me; } catch (MyException* pme) { std::cout << "In catch-block, pme points to 0x" << pme << std::endl; std::cout << "<" << pme->ObjId() << "> The exception has been caught. " << std::endl; std::cout << "____A____" << std::endl; } std::cout << "____B____" << std::endl; std::cout << std::endl; try { MyException* pme = new MyException; std::cout << "In try-block, pme points to 0x" << pme << std::endl; throw pme; } catch (MyException* pme) { std::cout << "In catch-block, pme points to 0x" << pme << std::endl; std::cout << "<" << pme->ObjId() << "> The exception has been caught. " << std::endl; std::cout << "____A____" << std::endl; } std::cout << "____B____" << std::endl; std::cout << std::endl; try { MyException* pme = new MyException; std::cout << "In try-block, pme points to 0x" << pme << std::endl; throw pme; } catch (MyException* pme) { std::cout << "In catch-block, pme points to 0x" << pme << std::endl; std::cout << "<" << pme->ObjId() << "> The exception has been caught. " << std::endl; delete pme; pme = NULL; std::cout << "____A____" << std::endl; } std::cout << "____B____" << std::endl; return 0; }

// Output <+1> MyException default constructor has been invoked. <+2> MyException copy constructor has been invoked. <-1> MyException destructor has been invoked. <2> The exception has been caught. ____A____ <-2> MyException destructor has been invoked. ____B____ <+1> MyException default constructor has been invoked. <+2> MyException copy constructor has been invoked. <+3> MyException copy constructor has been invoked. <-1> MyException destructor has been invoked. <3> The exception has been caught. ____A____ <-3> MyException destructor has been invoked. <-2> MyException destructor has been invoked. ____B____ <+1> MyException default constructor has been invoked. In try-block, address of me is 0x0038FBA0 <-1> MyException destructor has been invoked. In catch-block, pme points to 0x0038FBA0 <-100000> The exception has been caught. ____A____ ____B____ <+1> MyException default constructor has been invoked. In try-block, pme points to 0x003A1EA0 In catch-block, pme points to 0x003A1EA0 <1> The exception has been caught. ____A____ ____B____ <+2> MyException default constructor has been invoked. In try-block, pme points to 0x003A1ED8 In catch-block, pme points to 0x003A1ED8 <2> The exception has been caught. <-2> MyException destructor has been invoked. ____A____ ____B____

有时间再分析下输出.

你可能感兴趣的:(exception,delete,iostream,Constructor,编译器,destructor)