_ZNSaIwEC1Ev
_ZNSaIwEC2Ev
这两个C++符号不同,但是使用C++filt或类似工具解缠后,它们会变成相同的形式:
std::allocator<wchar_t>::allocator()
std::allocator<wchar_t>::allocator()
为什么会这样?可能是解缩器的缺陷还是其他什么原因?
g++使用由Itanium ABI指定的名称重载方案(以及其他实现细节)。
在构造函数和析构函数的重载部分中,我们可以看到:
<ctor-dtor-name> ::= C1 # complete object constructor
::= C2 # base object constructor
::= C3 # complete object allocating constructor
::= D0 # deleting destructor
::= D1 # complete object destructor
::= D2 # base object destructor
C1
,是直接用于初始化的普通构造函数。C2
,被派生类构造函数用来初始化其基类子对象。当涉及到虚继承时,这可以与“完整构造函数”不同,因为只有完整构造函数才会初始化虚基类,而基类构造函数则假定其虚基类已经被初始化。C3
,可能包括对operator new
的调用。但据我所知,g++实际上从未使用过这个。D0
,以调用适当的标量operator delete
结束。这是必要的,以便将其与虚析构函数绑定,因为正确的operator delete
可能是一个静态类成员,而基类对此一无所知。D1
,类似于C1
构造函数的反向操作,并包括虚基类的析构函数调用。D2
,类似于C2
构造函数的反向操作,并省略对虚基类的析构函数调用。因此,你所询问的C1
和C2
名称中包含的信息对于C++系统来说非常重要,必须正确地链接每个信息。但是,这些信息在伪代码声明中很难简要解释,因此解密函数只是将两个符号描述为相同的。
尽管std::allocator<T>
通常不具有任何虚基类,但很可能这两个符号实际上指向相同的代码地址,而g++提供了两个链接器符号以保持一致性。