深入解析C++ 中std::map內(nèi)存管理
1?、基本清空std::map
使用 clear() 可以刪除 map 中的所有元素,銷毀每個元素:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> myMap;
myMap[1] = "one";
myMap[2] = "two";
std::cout << "Before clear, size: " << myMap.size() << std::endl;
// 清空 map
myMap.clear();
std::cout << "After clear, size: " << myMap.size() << std::endl;
return 0;
}輸出:
Before clear, size: 2
After clear, size: 0
注意:clear() 只是刪除節(jié)點,不一定釋放底層內(nèi)存池分配的所有內(nèi)存(STL 可能保留內(nèi)存用于以后復(fù)用)。
2?、使用 swap 徹底釋放內(nèi)存
為了讓 STL 容器釋放所有內(nèi)存,可以和一個空 map 交換:
std::map<int, std::string>().swap(myMap);
等價于:
std::map<int, std::string> emptyMap; myMap.swap(emptyMap); // 將 myMap 與空 map 交換
- 優(yōu)點:保證底層內(nèi)存釋放
- 適合大 map 釋放內(nèi)存,避免內(nèi)存泄漏
3?、map 中存儲指針類型的對象
如果 map 中是指針類型,需要先釋放指針指向的內(nèi)存,否則會泄漏:
#include <map>
#include <string>
#include <iostream>
int main() {
std::map<int, std::string*> myMap;
myMap[1] = new std::string("one");
myMap[2] = new std::string("two");
// 手動釋放指針
for (auto& pair : myMap) {
delete pair.second;
}
myMap.clear(); // 刪除節(jié)點
// 或者徹底釋放內(nèi)存
std::map<int, std::string*>().swap(myMap);
std::cout << "Map cleared and memory released" << std::endl;
}4?、總結(jié)
| 操作 | 內(nèi)存釋放效果 | 適用場景 |
|---|---|---|
myMap.clear() | 刪除元素,可能不釋放底層節(jié)點內(nèi)存 | 小型 map 或可重復(fù)使用的 map |
std::map<…>().swap(myMap) | 刪除元素,釋放底層內(nèi)存 | 大型 map,徹底釋放內(nèi)存 |
對指針類型元素手動 delete | 釋放指針對象占用內(nèi)存 | map 存儲動態(tài)分配對象 |
5、擴展應(yīng)用示例-模板化函數(shù)free_map_memory內(nèi)存釋放
下面是一個 模板化函數(shù) free_map_memory,能自動處理 指針和非指針類型 map 的完全釋放,被封裝成可復(fù)用工具函數(shù),可以直接應(yīng)用到開發(fā)項目中,大家可根據(jù)自己的需求進行更改。
示例1,常規(guī)版本
#include <map>
#include <type_traits>
#include <memory> // std::addressof
#include <utility> // std::swap
#include <iostream>
template <typename MapType>
void free_map_memory(MapType& m) {
using ValueType = typename MapType::mapped_type;
// 如果 ValueType 是指針類型,先 delete 指針
if constexpr (std::is_pointer_v<ValueType>) {
for (auto& kv : m) {
delete kv.second;
}
}
// 清空 map 元素
m.clear();
// 徹底釋放底層內(nèi)存
MapType().swap(m);
}
// ------------------- 示例 -------------------
struct MyData {
int x;
MyData(int v) : x(v) {}
};
int main() {
std::map<int, int> normalMap;
normalMap[1] = 100;
normalMap[2] = 200;
std::map<int, MyData*> pointerMap;
pointerMap[1] = new MyData(10);
pointerMap[2] = new MyData(20);
std::cout << "Before free, normalMap size: " << normalMap.size() << std::endl;
std::cout << "Before free, pointerMap size: " << pointerMap.size() << std::endl;
free_map_memory(normalMap);
free_map_memory(pointerMap);
std::cout << "After free, normalMap size: " << normalMap.size() << std::endl;
std::cout << "After free, pointerMap size: " << pointerMap.size() << std::endl;
return 0;
}功能特點
- 自動識別值類型是否為指針:使用
std::is_pointer_v。 - 安全釋放指針類型對象:自動
delete。 - 徹底釋放 map 內(nèi)存:使用
swap與臨時空 map 交換。 - 通用:支持任何
std::map<Key, Value>類型,包括自定義結(jié)構(gòu)體指針。
示例2,智能指針版本
加強版本能自動識別并處理以下幾類 map:
- 值類型為普通對象
- 值類型為原始指針
- 值類型為
std::unique_ptr或std::shared_ptr
模板函數(shù)會自動釋放內(nèi)容并徹底回收 map 內(nèi)存。
#include <map>
#include <memory>
#include <type_traits>
#include <utility>
#include <iostream>
template <typename MapType>
void free_map_memory(MapType& m) {
using ValueType = typename MapType::mapped_type;
// 原始指針類型
if constexpr (std::is_pointer_v<ValueType>) {
for (auto& kv : m) {
delete kv.second;
}
}
// unique_ptr 或 shared_ptr 類型
else if constexpr (std::is_same_v<ValueType, std::unique_ptr<typename ValueType::element_type>> ||
std::is_same_v<ValueType, std::shared_ptr<typename ValueType::element_type>>) {
// 智能指針自動釋放,無需手動 delete
}
// 普通對象類型,無需特殊處理
// 清空 map 元素
m.clear();
// 徹底釋放底層內(nèi)存
MapType().swap(m);
}
// ------------------- 示例 -------------------
struct MyData {
int x;
MyData(int v) : x(v) {}
};
int main() {
// 普通對象 map
std::map<int, int> normalMap{{1,100},{2,200}};
// 原始指針 map
std::map<int, MyData*> pointerMap;
pointerMap[1] = new MyData(10);
pointerMap[2] = new MyData(20);
// unique_ptr map
std::map<int, std::unique_ptr<MyData>> uniquePtrMap;
uniquePtrMap[1] = std::make_unique<MyData>(30);
uniquePtrMap[2] = std::make_unique<MyData>(40);
// shared_ptr map
std::map<int, std::shared_ptr<MyData>> sharedPtrMap;
sharedPtrMap[1] = std::make_shared<MyData>(50);
sharedPtrMap[2] = std::make_shared<MyData>(60);
free_map_memory(normalMap);
free_map_memory(pointerMap);
free_map_memory(uniquePtrMap);
free_map_memory(sharedPtrMap);
std::cout << "All maps freed successfully." << std::endl;
return 0;
}功能特點
- 自動區(qū)分普通對象 / 原始指針 / 智能指針
- 原始指針自動
delete - 智能指針無需手動釋放
- 徹底回收 map 內(nèi)存,避免底層內(nèi)存占用
到此這篇關(guān)于C++ 中std::map內(nèi)存管理詳解的文章就介紹到這了,更多相關(guān)C++ td::map內(nèi)存管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳談C++ socket網(wǎng)絡(luò)編程實例(2)
這篇文章主要為大家介紹了C++ socket網(wǎng)絡(luò)編程實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-11-11
C++實現(xiàn)String與UF8互轉(zhuǎn)
這篇文章介紹了C++實現(xiàn)String與UF8互轉(zhuǎn)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
Visual?Studio2022配置ReSharper?C++?常用設(shè)置方法
這篇文章主要介紹了Visual?Studio2022配置ReSharper?C++?常用設(shè)置,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),文中介紹了卸載Resharper的方法及Resharper激活碼,感興趣的朋友參考下吧2024-01-01
C++實現(xiàn)LeetCode(110.平衡二叉樹)
這篇文章主要介紹了C++實現(xiàn)LeetCode(110.平衡二叉樹),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

