dynamic_cast
dynamic_cast是专门用于沿继承层次结构进行的强制类型转换,更像是一个函数, 不是编译时进行的类型转换,而是在运行时计算,正因如此,有小性能损失。
在基类和派生类之间相互转换。dynamic_cast常用来做验证,下图中开启运行时检查。
class Entity {
public:
virtual void PrintName9() {}
};
class Player : public Entity{};
class Enemy : public Entity{};
int main() {
Player* player = new Player();
Entity* e = player;
Enemy* e1 = new Enemy();
//Enemy* e2 = (Enemy*)e;
//Enemy* e2 = static_cast<Enemy*>(e);
Player* e2 = dynamic_cast<Player*>(e1);
Player* e3 = dynamic_cast<Player*>(e);
//类似Java可以进行类型验证
if (dynamic_cast<Player*>(e1) == NULL) {
std::cout << "error";
}
}
如果类型转换无效,就说明不是你声称的给定类型,那么就会返回null
使用需要rtti是打开状态,在绝大多数状态,打开会增加开销,但关闭可能会带来错误,如果只想优化,编写非常快的代码,需要避免使用。
基准测试
在这里复习了 如何编写计时类:
class Timer {
public:
Timer() {
m_StartTimepoint = std::chrono::high_resolution_clock::now();
}
~Timer() {
stop();
}
void stop() {
auto endTimepoint = std::chrono::high_resolution_clock::now();
auto start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
auto end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();
auto duration = end - start;
double ms = duration * 0.001;
std::cout << "ns:" << duration<< "(ms:" << ms << ")" << std::endl;
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTimepoint;
};
比较了三种方法创建指针的效率:
{
struct Vector2
{
float x, y;
};
{
std::array<std::shared_ptr<Vector2>, 1000> sharedPtrs;
Timer timer;
for (int i = 0; i < sharedPtrs.size(); i++) {
sharedPtrs[i] = std::make_shared<Vector2>();
}
}
{
std::array<std::shared_ptr<Vector2>, 1000> sharedPtrs;
Timer timer;
for (int i = 0; i < sharedPtrs.size(); i++) {
sharedPtrs[i] = std::shared_ptr<Vector2>();
}
}
{
std::array<std::unique_ptr<Vector2>, 1000> sharedPtrs;
Timer timer;
for (int i = 0; i < sharedPtrs.size(); i++) {
sharedPtrs[i] = std::make_unique<Vector2>();
}
}
}
结果是最后一种最快,第一种中间,第二种最慢,因为第三种unique指针效率最高,而第二种需要构造shared_ptr所以他效率最低。