异常处理时类型识别的工作原理 > C++代码中的某个地方: try { foo(); } catch (const FooExceptionOne& e) { // ... } catch (const FooExceptionTwo& e) { // ... } catch (const std::exception& e) { // ... }
异常处理时类型识别的工作原理 > C++代码中的某个地方: try { foo(); } catch (const FooExceptionOne& e) { // ... } catch (const FooExceptionTwo& e) { // ... } catch (const std::exception& e) { // ... },c++,exception,exception-handling,C++,Exception,Exception Handling,FooExceptionOne和FooExceptionTwo是从std::exception派生的自定义类 在抛出异常的时刻;类型识别是如何工作的?这是一种动态铸造或普利莫菲斯,发生在“引擎盖下” 我的第一个想法是动态的铸造,但是(当然)它看起来非常慢的解决方案。< /P> < P> GCC,Clang和英特尔C++编译器将这个类型推到登记册中,如在这个页面上可以看到的: 守则: switch (throwType) { case 0: throw 0; case 1:
FooExceptionOne
和FooExceptionTwo
是从std::exception
派生的自定义类
在抛出异常的时刻;类型识别是如何工作的?这是一种动态铸造或普利莫菲斯,发生在“引擎盖下”
我的第一个想法是动态的铸造,但是(当然)它看起来非常慢的解决方案。< /P> < P> GCC,Clang和英特尔C++编译器将这个类型推到登记册中,如在这个页面上可以看到的:
守则:switch (throwType) {
case 0:
throw 0;
case 1:
throw 0.0;
case 2:
throw "test";
}
在GCC中编译为以下汇编代码:
.L17:
mov edi, 4
call __cxa_allocate_exception
xor edx, edx
mov DWORD PTR [rax], 0
mov esi, OFFSET FLAT:typeinfo for int
mov rdi, rax
call __cxa_throw
.L4:
mov edi, 8
call __cxa_allocate_exception
xor edx, edx
mov QWORD PTR [rax], OFFSET FLAT:.LC1
mov esi, OFFSET FLAT:typeinfo for char const*
mov rdi, rax
call __cxa_throw
.L3:
mov edi, 8
call __cxa_allocate_exception
xor edx, edx
mov QWORD PTR [rax], 0x000000000
mov esi, OFFSET FLAT:typeinfo for double
mov rdi, rax
call __cxa_throw
从线条上可以看出:
mov esi, OFFSET FLAT:typeinfo for int
mov esi, OFFSET FLAT:typeinfo for char const*
mov esi, OFFSET FLAT:typeinfo for double
该类型的typeinfo在GCC中存储在esi
寄存器中。但是,这是特定于编译器的,因此,尽管这是GCC(以及Clang和Intel)的情况,但可能不适用于任何其他编译器(Borland等)
< > >代码> >代码>的类型信息可以在编译时完全确定,因此不需要使用C++的RTI特性,因为它基本上是一个ID类型的枚举,用于映射到相应的catch块。
确定类型映射方式的规则可在标准第15.3节“异常处理”中找到 看看下面的文章和文章
编译器将生成包含异常typeinfo的数组/表,用于try/catch搜索。不是答案,但异常应该由
const
引用捕获。我不确定它是如何工作的,但非常缓慢的解决方案在这里不是问题。例外情况不是为速度而设计的。