修复std :: map

时间:2015-10-26 13:19:40

标签: c++ performance dictionary memory-leaks

我遇到了这样的问题:可能的内存泄漏 想象一下,如果为同一个密钥存储两个不同的堆指针。

#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? 你有什么建议来解决内存泄漏并坚持对数复杂性?

编辑:重构非常省钱,我正在寻找没有智能指针的解决方案。

4 个答案:

答案 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;
}