gpt4 book ai didi

c++ - typeid 的成本是多少?

转载 作者:可可西里 更新时间:2023-11-01 15:40:21 44 4
gpt4 key购买 nike

我正在考虑使用 typeid 来解析类型的类型删除设置......

struct BaseThing
{
virtual ~BaseThing() = 0 {}
};

template<typename T>
struct Thing : public BaseThing
{
T x;
};

struct A{};
struct B{};

int main()
{
BaseThing* pThing = new Thing<B>();
const std::type_info& x = typeid(*pThing);

if( x == typeid(Thing<B>))
{
std::cout << "pThing is a Thing<B>!\n";
Thing<B>* pB = static_cast<Thing<B>*>(pThing);
}
else if( x == typeid(Thing<A>))
{
std::cout << "pThing is a Thing<A>!\n";
Thing<A>* pA = static_cast<Thing<A>*>(pThing);
}
}

我从未见过其他人这样做过。另一种方法是让 BaseThing 有一个纯虚拟的 GetID(),它将用于推断类型而不是使用 typeid。在这种情况下,只有 1 级继承,typeid 的成本与虚函数调用的成本是多少?我知道 typeid 以某种方式使用 vtable,但它究竟是如何工作的?

这会比 GetID() 更好,因为它需要相当多的技巧来确保 ID 是唯一的确定性的。

最佳答案

The alternative would be for BaseThing to have a pure virtual GetID() which would be used to deduce the type instead of using typeid. In this situation, with only 1 level of inheritance, what's the cost of typeid vs the cost of a virtual function call? I know typeid uses the vtable somehow, but how exactly does it work?

在 Linux 和 Mac 上,或任何其他使用 Itanium C++ ABI 的平台上,typeid(x) 编译成两条加载指令——它只是加载 vptr(即某个 vtable 的地址)对象 x 的前 8 个字节,然后从该 vtable 加载第 -1 指针。该指针是 &typeid(x)。这是一个函数调用,比调用虚拟方法成本更低

在 Windows 上,它涉及四个 加载指令和几个(可忽略的)ALU 操作,因为 Microsoft C++ ABI 是 a bit more enterprisey . ( source ) 老实说,这最终可能与虚拟方法调用不相上下。但与 dynamic_cast 相比,这仍然非常便宜。

dynamic_cast 涉及对 C++ 运行时的函数调用,它具有很多加载和条件分支等。

所以是的,利用 typeiddynamic_cast 快得多。它对您的用例来说是否正确?—这是值得怀疑的。 (请参阅有关 Liskov 可替代性等的其他答案。)但是它会快吗?— 是的。

在这里,我从 Vaughn 的高评价答案中提取了玩具基准代码,并将其放入 an actual benchmark 中。 ,避免了明显的循环提升优化,这让他所有的时间都变得乏味。结果,对于我的 Macbook 上的 libc++abi:

$ g++ test.cc -lbenchmark -std=c++14; ./a.out
Run on (4 X 2400 MHz CPU s)
2017-06-27 20:44:12
Benchmark Time CPU Iterations
---------------------------------------------------------
bench_dynamic_cast 70407 ns 70355 ns 9712
bench_typeid 31205 ns 31185 ns 21877
bench_id_method 30453 ns 29956 ns 25039

$ g++ test.cc -lbenchmark -std=c++14 -O3; ./a.out
Run on (4 X 2400 MHz CPU s)
2017-06-27 20:44:27
Benchmark Time CPU Iterations
---------------------------------------------------------
bench_dynamic_cast 57613 ns 57591 ns 11441
bench_typeid 12930 ns 12844 ns 56370
bench_id_method 20942 ns 20585 ns 33965

(越小的 ns 越好。您可以忽略后两列:“CPU”只是表明它所有的时间都在运行,没有时间等待,而“Iterations”只是运行以获得良好的误差范围。)

您可以看到 typeid 击败 dynamic_cast 甚至在 -O0 时,但是当您打开优化时,它会做得更好 — 因为编译器可以优化 编写的任何代码。 All that ugly code hidden inside libc++abi's __dynamic_cast function编译器无法再对其进行优化,因此启用 -O3 并没有多大帮助。

关于c++ - typeid 的成本是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8094805/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com