[原创](Modern C++)现代C++的关键性概念: 用低内存开销的方式来操作C++标准容器
[作者]
常用网名: 猪头三
出生日期: 1981.XX.XX
企鹅交流: 643439947
个人网站: 80x86汇编小站
编程生涯: 2001年~至今[共24年]
职业生涯: 22年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测
[序言]
在现代C++开发中, 标准容器(如 std::map、std::vector 等)提供了强大的数据存储和管理能力. 然而在处理大量数据时, 如果不加以优化, 可能会带来额外的性能开销, 特别是在涉及到对象的拷贝和构造时. 在本篇博客中, 将探讨如何通过存储std::map的迭代器来避免数据拷贝, 从而降低内存使用, 同时结合std::ranges::sort进行高效排序, 以最大限度地优化容器操作的开销.
[代码演示]
int main()
{
// 初始化一个 std::map 容器
std::map<int, std::tuple<float, float>> map_Demo = {
{1, {100.5f, 105.3f}},
{4, {99.2f, 101.8f}},
{3, {105.0f, 110.0f}},
{2, {98.5f, 99.3f}},
{5, {102.0f, 104.7f}}
};
// 直接存储 std::map 内部元素的迭代器, 避免拷贝整个元素
std::vector<std::map<int, std::tuple<float, float>>::iterator> vector_Demo ;
for (auto iterator_Item = map_Demo.begin(); iterator_Item != map_Demo.end(); ++iterator_Item)
{
vector_Demo.emplace_back(iterator_Item);
}
// 使用 std::ranges::sort 进行排序, 避免额外的构造开销
std::ranges::sort(vector_Demo.begin(), vector_Demo.end(),
[](const auto& item_A, const auto& item_B) {
return std::get<1>(item_A->second) > std::get<1>(item_B->second);
});
return 0;
}
[代码说明]
* 数据结构初始化:
使用std::tuple来存储每个键值对的两个浮点数值, 这样的结构允许在一个容器中存储不同类型的数据, 而无需创建额外的类或结构体.
* 存储迭代器以避免数据拷贝:
通过保存std::map的迭代器到std::vector中, 而不是保存元素的副本, 可以大大减少内存使用, 因为迭代器仅仅是指向原数据的指针, 并不在堆上创建新的对象.
* 使用std::ranges::sort进行排序:
std::ranges::sort是C++20引入的排序方法, 与传统的std::sort相比, 它提供了更简洁的接口, 可以直接作用于begin()和end()迭代器, 免了不必要的迭代器解引用. 由于vector_Demo存储的是迭代器, 排序过程中不会发生std::map元素的拷贝.
[总结]
在现代C++中操作标准容器时, 一种降低内存开销的有效策略, 可通过存储元素的迭代器而非副本, 结合std::ranges的高效操作, 我可以在不牺牲性能的前提下, 显著减少内存占用.
1. 使用迭代器存储而非直接存储容器元素, 避免了std::map元素的拷贝, 从而降低内存和CPU开销.
2. 利用std::ranges, 以减少额外的构造和拷贝开销, 使代码更简洁和高效.
3. 基于std::tuple, std::pair元素, 可以适用于类似的数据结构优化.