深入解析C++ 中std::map內(nèi)存管理
1?、基本清空std::map
使用 clear() 可以刪除 map 中的所有元素,銷毀每個(gè)元素:
#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é)點(diǎn),不一定釋放底層內(nèi)存池分配的所有內(nèi)存(STL 可能保留內(nèi)存用于以后復(fù)用)。
2?、使用 swap 徹底釋放內(nèi)存
為了讓 STL 容器釋放所有內(nèi)存,可以和一個(gè)空 map 交換:
std::map<int, std::string>().swap(myMap);
等價(jià)于:
std::map<int, std::string> emptyMap; myMap.swap(emptyMap); // 將 myMap 與空 map 交換
- 優(yōu)點(diǎn):保證底層內(nèi)存釋放
- 適合大 map 釋放內(nèi)存,避免內(nèi)存泄漏
3?、map 中存儲(chǔ)指針類型的對(duì)象
如果 map 中是指針類型,需要先釋放指針指向的內(nèi)存,否則會(huì)泄漏:
#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");
// 手動(dòng)釋放指針
for (auto& pair : myMap) {
delete pair.second;
}
myMap.clear(); // 刪除節(jié)點(diǎn)
// 或者徹底釋放內(nèi)存
std::map<int, std::string*>().swap(myMap);
std::cout << "Map cleared and memory released" << std::endl;
}4?、總結(jié)
| 操作 | 內(nèi)存釋放效果 | 適用場(chǎng)景 |
|---|---|---|
myMap.clear() | 刪除元素,可能不釋放底層節(jié)點(diǎn)內(nèi)存 | 小型 map 或可重復(fù)使用的 map |
std::map<…>().swap(myMap) | 刪除元素,釋放底層內(nèi)存 | 大型 map,徹底釋放內(nèi)存 |
對(duì)指針類型元素手動(dòng) delete | 釋放指針對(duì)象占用內(nèi)存 | map 存儲(chǔ)動(dòng)態(tài)分配對(duì)象 |
5、擴(kuò)展應(yīng)用示例-模板化函數(shù)free_map_memory內(nèi)存釋放
下面是一個(gè) 模板化函數(shù) free_map_memory,能自動(dòng)處理 指針和非指針類型 map 的完全釋放,被封裝成可復(fù)用工具函數(shù),可以直接應(yīng)用到開發(fā)項(xiàng)目中,大家可根據(jù)自己的需求進(jìn)行更改。
示例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;
}功能特點(diǎn)
- 自動(dòng)識(shí)別值類型是否為指針:使用
std::is_pointer_v。 - 安全釋放指針類型對(duì)象:自動(dòng)
delete。 - 徹底釋放 map 內(nèi)存:使用
swap與臨時(shí)空 map 交換。 - 通用:支持任何
std::map<Key, Value>類型,包括自定義結(jié)構(gòu)體指針。
示例2,智能指針版本
加強(qiáng)版本能自動(dòng)識(shí)別并處理以下幾類 map:
- 值類型為普通對(duì)象
- 值類型為原始指針
- 值類型為
std::unique_ptr或std::shared_ptr
模板函數(shù)會(huì)自動(dòng)釋放內(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>>) {
// 智能指針自動(dòng)釋放,無需手動(dòng) delete
}
// 普通對(duì)象類型,無需特殊處理
// 清空 map 元素
m.clear();
// 徹底釋放底層內(nèi)存
MapType().swap(m);
}
// ------------------- 示例 -------------------
struct MyData {
int x;
MyData(int v) : x(v) {}
};
int main() {
// 普通對(duì)象 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;
}功能特點(diǎn)
- 自動(dòng)區(qū)分普通對(duì)象 / 原始指針 / 智能指針
- 原始指針自動(dòng)
delete - 智能指針無需手動(dòng)釋放
- 徹底回收 map 內(nèi)存,避免底層內(nèi)存占用
到此這篇關(guān)于C++ 中std::map內(nèi)存管理詳解的文章就介紹到這了,更多相關(guān)C++ td::map內(nèi)存管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)選擇排序(selectionSort)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)選擇排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
通過c++11改進(jìn)我們的模式之改進(jìn)命令模式
這篇我要講的是如何使用c++11改進(jìn)命令模式,感興趣的朋友可以看下2013-11-11
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易五子棋
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易五子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
在Visual Studio中配置C++最新版netCDF庫(kù)的方法
本文介紹在Windows電腦的Visual Studio軟件中,配置C++ 語(yǔ)言最新版netCDF庫(kù)的方法,文中通過圖文結(jié)合的形式介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-03-03
VisualStudio?制作Dynamic?Link?Library動(dòng)態(tài)鏈接庫(kù)文件的詳細(xì)過程
這篇文章主要介紹了VisualStudio?制作Dynamic?Link?Library動(dòng)態(tài)鏈接庫(kù)文件的詳細(xì)過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
Matlab實(shí)現(xiàn)生成箭頭坐標(biāo)軸詳解
這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)生成箭頭坐標(biāo)軸,為坐標(biāo)軸增添箭頭,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下2022-03-03
C++使用OpenCV進(jìn)行物體識(shí)別與檢測(cè)的三種方法
物體識(shí)別與檢測(cè)是計(jì)算機(jī)視覺中的核心任務(wù)之一,它被廣泛應(yīng)用于自動(dòng)駕駛、安防監(jiān)控、圖像分析等領(lǐng)域,通過物體檢測(cè)技術(shù),計(jì)算機(jī)能夠從圖像中識(shí)別出特定的物體或目標(biāo),本文將介紹如何使用 C++ 和 OpenCV 庫(kù)進(jìn)行物體識(shí)別與檢測(cè),需要的朋友可以參考下2025-04-04

