使用 static_cast 处理混合(基础和派生)对象的向量是否存在性能风险?(又名 "it this a dumb idea?" )
Are there performance risks for using static_cast to deal with a vector of mixed (base & derived) objects? (aka "it this a dumb idea?")
给定gameObject
的基类和animatedGameObject
的派生类,我认为将它们的所有实例存储在std::vector
中可能会很好。如果向量GameObjects
被声明为gameObject*
的基类型,则派生的对象实例需要强制转换。
示例:
vector<gameObject*> GameObjects;
gameObject A* = new gameObject( ...init... );
animatedGameObject B* = new animatedGameObject( ...init... );
GameObjects.push_back(A);
GameObjects.push_back(B);
// to access the animatedGameObject functions:
static_cast<animatedGameObject*>(GameObjects[1])->functionUniqueToAnimated();
像往常一样害怕,我求助于Scott Meyers(有效C++,第三版),他写的主题是:
许多程序员认为,强制转换只会告诉编译器将一种类型视为另一种类型,但这是错误的。任何类型的类型转换(通过强制转换显式转换或通过编译器隐式转换)通常都会导致在运行时执行代码
我已经读了两遍他的第27项:最小化施法,但鉴于我对此缺乏经验,我很难回答一个简单的问题"这是一件愚蠢的事情吗?"
我应该提到的是,它之所以是一件愚蠢的事情,有几个原因与调用static_cast
无关。按重要性排序的问题是:
- 在上面的例子中,我没有看到使用
static_cast
可能存在的风险吗 - 对于这种方法,是否有比
std::vector
更好的数据结构?(如果有一个是显而易见的,我不会要求你为我做研究。)
这是我第一次在这里提问,所以在必要的时候提前道歉。
static_cast
不是适用于作业的工具,除非您知道指针指向的是animatedGameObject
而不是gameObject
。您使用什么数据结构来存储这些信息?
在基指针之后确定派生对象的类型是动态调度或dynamic_cast
的工作。在您的示例中,调用GameObjects[1]->draw()
应该不带强制转换,因为draw
应该是一个虚拟函数。否则,您可以使用dynamic_cast< animatedGameObject & >( * GameObjects[1] )
断言该对象是动画游戏对象,如果不是,则抛出std::bad_cast
异常。(这仍然需要class gameObject
中的virtual
函数,通常是其析构函数。)
但对多态派生类型执行static_cast
是一种代码气味。
此外,您还询问std::vector
对于这个用例是否是一个好的数据结构。它是,但不是"裸"指针的矢量。C++11现在提供了"智能指针"内存管理类,它们为您执行new
和delete
,使实际运算符几乎过时。对于这种情况,请查看std::unique_ptr
。
- 若gameObjects[1]并没有动画化GameObject,应用程序(很可能)会惨死
- 如果draw()是gameObject中存在的虚拟方法,则不需要转换
通常,将基类强制转换为派生类是不安全的。在这些情况下,使用dynamic_cast是有意义的。如果无法执行转换,Dynamic_cast将返回NULL。
有比更好的数据结构吗
好吧,如果你的gameObjects没有在其他地方自动删除,那么使用std::vector<std::shared_ptr<gameObject> >
之类的东西可能是有意义的。然而,标准共享指针可能会引入隐藏的开销(额外的新/删除,在最坏的情况下,如果它们被设计为线程安全的,它们甚至可能引入多线程互斥锁),所以你应该确保这些开销与你的目标兼容。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 在类中使用随机生成器时出现性能问题
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 海湾合作委员会 ARM 性能下降
- GCC 和 Clang 代码性能的巨大差异
- 在容量内调整矢量大小时的性能影响
- 了解算法的性能差异(如果以不同的编程语言实现)
- 未达到的情况会影响开关外壳性能
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 是否总是可以将使用递归编写的程序重写为不使用递归的程序C++,性能观点是什么?
- 哪种方法更好,性能明智
- C++ 特征库:引用的性能开销<>
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- 基于范围的 for 循环range_declaration中各种说明符之间的性能差异
- std::p mr::memory_resource 如何与 std::container 产生性能差异?
- 使用 static_cast 处理混合(基础和派生)对象的向量是否存在性能风险?(又名 "it this a dumb idea?" )