这种人工剥夺机会的做法合法/可行吗
Is this manual devirtualization legal / viable?
本文关键字:机会 更新时间:2023-10-16
对于我的一个项目,我终于需要使用我的第一个多态类(std::cout除外(。
我正在研究如何确保我有100%的电话——至少在某些情况下是这样。
这个守则合法可行吗?
dynamic_cast
会有多慢?如果我在构造函数中支付一次,那么我将始终能够直接使用类B
,所以这听起来是一个好的练习?
在那之后,C风格的转换会很快吗?还是我必须存储指向B
的指针?
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct X{
A *a;
bool fB;
X(A &a) : a(&a), fB( dynamic_cast<B *>(&a) ){}
void f(){
if (fB){
((B*)a)->x();
}else{
a->x();
}
}
};
void fn(A &a){
X x(a);
x.f();
}
int main(){
B b;
X x(b);
x.f();
}
对于您现有的代码,我实际上希望您的编译器优化掉if语句和您的强制转换,因为这会使代码变得不那么简单。
从编译器的角度来看,您的代码库可能如下所示:
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct C : B{
void x() override;
};
因此,当is看到您的强制类型和函数调用:static_cast<B*>(a)->x()
时,它仍然必须访问与调用a->x()
时相同的虚拟表,因为可能存在潜在的类C。(请注意,我使用static_cast,因为c样式转换是错误的来源(
如果您想直接调用B,最好将方法或类设为final
。另一个好的方法是使用概要文件引导的优化,在这种情况下,他们经常比较vtable指针。
回答你的附带问题?
- 代码合法吗?是的,是的
- 这可行吗?是的,考虑到上面的评论
- dynamic_cast的速度有多慢?慢慢来,我会争辩为这写一个好的基准,然而,我不知道如何做到这一点,并使其变得现实
- 这种做法好吗?不,这会降低多态性的可用性
- static_cast会很快吗?是的,它很快,在这种特殊情况下,不需要任何说明。与bool相比,在复杂继承的特定情况下,存储指向B的指针都可以改进。如果它需要额外的内存,也可能导致性能下降。只要在可执行文件中有额外的程序集,就可以实现另一个减少
我的建议,尤其是因为你是C++的新手:不要这样做或任何其他手动优化。编译器可以为您做很多工作。每次手动优化之后都会导致额外的维护,只有当您确实有性能问题时,才可以使用这些技巧。
哦,如果你想知道实际的汇编代码是什么,你可以在编译器资源管理器上进行实验
您尝试更改对分支的虚拟调用。
我已经不确定它是否更快了,
但更糟糕的是,您不能删除虚拟调用,因为B
可以有子子通道,您至少必须使void B::x() final
允许编译器取消调用的机会。
若编译器可以像main
中那样访问具体类型(和代码(,它可能能够单独取消调用的机会。
相关文章:
- gcc 是否在 2 条短裤的过度对齐结构的比较中错过了优化机会?
- 这是否错失了优化机会
- 这种人工剥夺机会的做法合法/可行吗
- DLL+导出类+模板成员func=未解析的外部符号.任何修复的机会
- 当删除或删除[]被执行时,计算机会做什么?
- GCC缺少优化CTOR初始化器列表的机会
- 有没有机会触发一个不知道拥有队列的kevent?还有其他选择吗?
- 是否有机会更快地使双线性插值
- 拥有用于动态机会/概率的简单负载均衡器(在C++中,但语言无关)
- Visual C++:在明显的情况下没有机会
- 对于一对碰撞机会较低的INT的最小哈希功能是什么
- 在Visual studio中调试javaScript.第一次机会例外
- 实施第二次机会需求页面替换算法
- 指针浮动阵列的第一个机会例外
- GCC中的CRTP与失机会标志
- C++ 切换声明 - 给玩家另一个选择的机会
- BunkerBuilder.exe中0x0070C75C处的首次机会异常:0xC0000005:写入位置0xCCCCC0
- 首次机会异常设置检查列表视图中的状态
- 模板的通用包装器:优化机会
- 创建CFrameWnd会给出第一次机会的异常——为什么