b站Cherno的课[71]-[75]
- 一、现代C++中的安全以及如何教授
- 二、C++的预编译头文件PCH
- 三、C++的dynamic_cast
- 四、C++的基准测试
- 五、C++的结构化绑定
一、现代C++中的安全以及如何教授
安全编程,或者说C++编程中,降低崩溃,内存泄露、非法访问等问题
C++11,智能指针,而不是原始指针,想要分配堆内存
用于生产环境使用智能指针,用于学习和了解工作积累,使用原始指针,当然,如果你需要定制的话,也可以使用自己写的智能指针
二、C++的预编译头文件PCH
precompiled header(预编译头文件)
预编译的头文件实际上是让你抓取一堆头文件,并将它们转换成编译器可以使用的格式,而不必一遍又一遍地读取这些头文件
使用预编译头文件,可以加速编译时间,它们也使实际编写代码更加方便
因为你不需要一遍又一遍地去包含常用的头文件
尤其在持续集成(CI)和频繁构建的场景下效果更为明显
三、C++的dynamic_cast
dynamic casting 动态转换类型
C++风格的转换
只能在C++中用不能在C
更像是一个函数,它不像编译时进行的类型转换,而是在运行时计算
dynamic_cast 是一种用于在运行时安全执行向下转型(downcasting)或跨继承层次转型的运算符。它是C++运行时类型识别**(RTTI)机制的一部分,核心目的是确保类型转换的安全性**。
// 指针类型转换
Derived* pd = dynamic_cast<Derived*>(base_ptr);// 引用类型转换(失败时抛出异常)
Derived& rd = dynamic_cast<Derived&>(base_ref);
dynamic_cast 专门用于沿继承层次结构进行的强制类型转换
RTTI 运行时类型信息(runtime type information)
它存储我们的所有类型的运行时类型信息
增加开销,但它可以让你做动态类型转换之类的事情
#include <iostream>
#include <string>class Entity
{
};class Player :public Entity
{
};class Enemy :public Entity
{
};
int main()
{ Player* player = new Player();Entity* actuallyEnemy = new Enemy();Entity* actuallyEnemy = player;Player* p0 = dynamic_cast<Player*>(actuallyEnemy);Player* p1 = dynamic_cast<Player*>(actuallyPlayer);std::cin.get();
}
关闭后出现警告:dynamic cast’ used on polymorphic type Entity with /
GR-,/GR-的意思是我们关掉了RTTI,给我们带来不可预测的行为
dynamic_cast 是C++中实现安全类型转换的关键工具,但其使用应遵循以下原则:
必要性:仅在必须进行运行时类型检查时使用。
安全性:始终检查转换结果(指针)或捕获异常(引用)。
设计优先:优先通过多态和良好的类设计减少类型转换需求。
四、C++的基准测试
#include <iostream>
#include <memory>int main()
{ int value = 0;for (int i = 0; i < 1000000; i++)value += 2;std::cout << value << std::endl;__debugbreak();
}
#include <iostream>
#include <memory>#include <chrono>
#include <array>class Timer
{
public:Timer(){m_StartTimepoint = std::_NO_SUCH_PROCESS::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 stop = std::chrono::time_point_cast<std::chrono::microseconds>(endTmiepoint).time_since_epoch().count();auto duration = end - start;double ms = duration * 0.001;std::cout << duration << "us (" << ms << "ms )\n";}private:std::chrono::time_point< std::chrono::high_resolution_clock> m_StartTimepoint;
};int main()
{ int value = 0;{Timer timer;for (int i = 0; i < 1000000; i++)value += 2;}std::cout << value << std::endl;__debugbreak();
}
#include <iostream>
#include <memory>#include <chrono>
#include <array>class Timer
{
public:Timer(){m_StartTimepoint = std::_NO_SUCH_PROCESS::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 stop = std::chrono::time_point_cast<std::chrono::microseconds>(endTmiepoint).time_since_epoch().count();auto duration = end - start;double ms = duration * 0.001;std::cout << duration << "us (" << ms << "ms )\n";}private:std::chrono::time_point< std::chrono::high_resolution_clock> m_StartTimepoint;
};int main()
{ struct Vector2{float x, y;};std::cout << "Make Shared\n";{std::array<std::shared_pr<Vector2>,1000> sharedPtrs;Timer timer;for (int i = 0; i < sharedPtrs.size(); i++)sharedPtrs[i] = std::make_shared<Vector2>();}std::cout << "New Shared\n";{std::array<std::shared_pr<Vector2>,1000> sharedPtrs;Timer timer;for (int i = 0; i < sharedPtrs.size(); i++)sharedPtrs[i] = std::shared_ptr<Vector2>(new Vector2());}std::cout << "Make Unique\n";{std::array<std::unique_pr<Vector2>, 1000> sharedPtrs;Timer timer;for (int i = 0; i < sharedPtrs.size(); i++)sharedPtrs[i] = std::make_unique<Vector2>();}__debugbreak();
}
五、C++的结构化绑定
Istructured bindings(结构化绑定)
只针对C++17
结构化绑定是一个新特性,让我们更好的处理多返回值
在C++17中,结构化绑定(Structured Bindings) 是一种简化多变量初始化的语法,允许将数组、结构体或元组等复合类型的成员直接绑定到独立的变量上,提升代码可读性和简洁性。
auto [var1, var2, ..., varN] = expression; // 值拷贝
auto& [var1, var2, ..., varN] = expression; // 引用绑定
#include <iostream>
#include <string>
#include <tuple>std::tuple<std::string, int> CreatePerson()
{return { "Cherno", 24 };
}int main()
{std::string name;int age;std::tie(name, age) = CreatePerson();
}
实际上一个结构体来给要返回的参数组命名有助于提升代码可读性,而且还可以方便的处理重名问题
通过结构化绑定,C++代码可以更直观地处理复合数据,减少冗余变量声明,同时保持类型安全和性能。它是现代C++中提升代码简洁性的重要工具之一。