我遇到了这样的问题:可能的内存泄漏 想象一下,如果为同一个密钥存储两个不同的堆指针。
#include <map>
std::map<int, int*> myMap;
void Store(int key, int* value)
{
myMap[key] = value;
}
int main()
{
Store(42, new int(42));
Store(35, new int(35));
delete myMap[42];
delete myMap[35];
}
我考虑过这样修复:
#include <map>
std::map<int, int*> myMap;
void Store(int key, int* value)
{
auto it = myMap.find(key);
if (it != myMap.end()))
{
delete it->second;
it->second = value;
}
else
{
myMap[key] = value;
}
}
int main()
{
Store(42, new int(42));
Store(35, new int(35));
delete myMap[42];
delete myMap[35];
}
但现在有两个对数查找而不是一个......
然后我想到了以下代码,
#include <map>
std::map<int, int*> myMap;
void Store(int key, int* value)
{
auto& mappedValue = myMap[key];
if (mappedValue == nullptr)
{
mappedValue = value;
}
else
{
delete mappedValue;
mappedValue = value;
}
}
int main()
{
Store(42, new int(42));
Store(35, new int(35));
delete myMap[42];
delete myMap[35];
}
但是,如果没有关联值,我怎么能确定mappedValue总是指向nullptr?
你有什么建议来解决内存泄漏并坚持对数复杂性?
编辑:重构非常省钱,我正在寻找没有智能指针的解决方案。
答案 0 :(得分:3)
但是如果没有关联值,我怎么能确定mappedValue总是指向nullptr?
如果operator[]
添加了新元素,则为value-initialized。对于非类型类型作为指针,这相当于零初始化,而在指针的情况下,这也是nullptr
。请参阅std::map::operator[]
。
答案 1 :(得分:2)
您可以考虑使用RAII in the form of smart pointers,而是将地图定义为
#include <map>
#include <memory>
std::map<int, std::shared_ptr<int>> myMap;
(为此,请确保将编译器配置为c++11模式。)
你的地图变成了这样的:将整数映射到类似指针的对象,它将负责解除分配。
答案 2 :(得分:1)
使用新标准c ++ 11,std::unique_ptr
是您的朋友。它没有任何开销,并提供内存安全性:
std::map<int, std::unique_ptr<int>> myMap;
void Store(int key, int* value)
{
myMap[key] = std::unique_ptr<int>{value};
}
int main()
{
Store(42, new int(42));
Store(35, new int(35));
}
没有内存泄漏。 如果您可以访问c ++ 14,您甚至可以这样做:
std::map<int, std::unique_ptr<int>> myMap;
void Store(int key, std::unique_ptr<int> value)
{
myMap[key] = std::move(value);
}
int main()
{
Store(42, std::make_unique<int>(42));
Store(35, std::make_unique<int>(35));
}
没有新的,没有删除。没有内存泄漏和安全。
答案 3 :(得分:1)
为什么不使用map :: insert
auto res = myMap.insert(std::make_pair(key,value));
if ( ! res.second ) {
delete res.first->second;
res.first->second = value;
}