std::type_info::name()的实际用途是什么

What is the actual purpose of std::type_info::name()?

本文关键字:是什么 type info name std      更新时间:2023-10-16

今天我的一位同事来问我标题中提到的问题
他目前正试图减少代码库的二进制足迹,该代码库也用于小型目标(如Cortex M3等)。显然,他们已经决定在打开RTTI的情况下进行编译(实际上是GCC),以支持正确的异常处理。

好吧,他的主要抱怨是为什么实际上需要std::type_info::name()来支持RTTI,并问道,我是否知道一种方法来抑制支持这一点所需的字符串文字的生成,或者至少缩短它们。

std::type_info::name

const char* name() const;返回一个实现定义的以null结尾的字符串,该字符串包含类型的名称。没有给出任何保证,特别是,对于几种类型,返回的字符串可能是相同的,并且在同一程序的调用之间会发生变化。

例如,dynamic_cast<>运算符的实现(尽管是编译器特定的)不会使用此信息,而是类似于用于类型确定的散列标记(类似于具有异常处理的catch()块)
我认为的现行标准定义清楚地表达了后者

  1. std::type_info::hash_code
  2. std::type_index

我不得不同意,除了用于调试(日志记录)之外,我也不认为使用std::type_info::name()有什么意义。我不能100%确定在没有RTTI的情况下,异常处理是否能在当前版本的GCC中工作(我认为他们使用的是4.9.1),所以我犹豫是否建议简单地关闭RTTI
此外,在他们的代码库中使用了dynamic_casts<>,但对于这些,我只是建议不要使用它,而使用static_cast(它们实际上没有插件之类的东西,也不需要断言之外的运行时类型检测)。


问题:

  • 除了日志记录之外,std::type_info::name()是否还存在现实生活中的生产代码级别用例

子问题(更具体):

  • 有人知道如何克服(解决)这些无用字符串文字的生成(假设它们永远不会被使用)吗?

  • RTTI真的(仍然)需要支持GCC的异常处理吗
    (@Sehe的回答很好地解决了这一部分,我已经接受了。对于代码中使用的任何异常,剩下的生成的std::type_info实例仍然存在另一个子问题。我们非常确信,这些文字从未在任何地方使用过)


相关位:剥离膨胀可执行文件(GCC)的未使用的运行时函数

隔离此位:

  • 关键是,如果他们关闭RTTI,异常处理在GCC中还能正常工作吗?——πάγταῥεῖ1小时前

答案是肯定的:

-fno-rtti

禁用生成关于每个具有虚拟函数的类的信息,以供C++运行时类型标识功能(dynamic_casttypeid)使用。如果你不使用语言的这些部分,你可以通过使用这个标志来节省一些空间请注意,异常处理使用相同的信息,但它会根据需要生成信息dynamic_cast运算符仍然可以用于不需要运行时类型信息的强制转换,即强制转换为void *或明确的基类。

除了日志记录之外,std::type_info::name()是否还存在现实生活中的生产代码级别用例?

安腾ABI描述了std::type_info对象的operator==是如何通过测试从std::type_info::name()返回的字符串来实现指针相等的。

在非平面地址空间中,可能具有相同类型的多个type_info对象(例如,因为动态库已加载了RTLD_LOCAL),operator==的实现可能需要使用strcmp来确定两个类型是否相同。

因此,name()函数用于确定两个type_info对象是否引用相同的类型。对于真实用例的示例,它通常至少在标准库中的两个位置使用,即std::function<F>::target<T>()std::get_deleter<D>(const std::shared_ptr<T>&)

如果您不使用RTTI,那么所有这些都无关紧要,因为您无论如何都不会有任何type_info对象(因此在libstdc++中不能使用function::targetget_deleter函数)。

我认为GCC的异常处理代码使用type_info对象本身的地址,而不是name()返回的字符串的地址,所以如果您使用异常但没有RTTI,则不需要name()字符串。