在类的构造函数中初始化映射时,如何避免内存泄漏?

时间:2019-05-11 13:29:55

标签: c++ class dictionary memory memory-leaks

我想在一个类的构造函数中初始化一个(指向a的指针)map。我编写的程序可以编译,但是由于分段错误而在运行时失败。我可以通过为map动态分配内存来解决问题,但是Valgrind会通知我有关内存泄漏的信息。如何正确初始化类?

这是一个例子

#include <iostream>
#include <map>
#include <string>
#include <vector>

class MemoryLeak {
   public:
    MemoryLeak(std::vector<std::string>& inp) {
        int i = 0;
        std::map<std::string, int>* tmp = new std::map<std::string, int>;
        for (std::string& s : inp) {
            //(*problem_map)[s] = i++; // Line 12: causes a seg fault
            (*tmp)[s] = i++;
        }
        problem_map = tmp;  // Line 15: memory leak
    }
    std::map<std::string, int>* problem_map;
};

int main() {
    std::vector<std::string> input{"a", "b"};
    MemoryLeak mem = MemoryLeak(input);
    for (auto const& it : *(mem.problem_map)) {
        std::cout << it.first << ": " << it.second << "\n";
    }
    return 0;
}

当我取消注释line 12(并注释掉Line 15)时,程序会编译,但似乎发生了内存泄漏。有人可以告诉我我在做什么错吗?一个更合适的构造函数会是什么样子?

1 个答案:

答案 0 :(得分:2)

对于 segfault

您的指针problem_map在第12行未初始化。 那就是为什么出现段错误。 您不需要tmp即可:

problem_map = new std::map<std::string, int>;
for (std::string& s : inp) {
    (*problem_map)[s] = i++; 
}

现在泄漏,您有两种选择:

1)添加一个析构函数,一个复制构造函数和一个复制分配运算符(或将其删除)。请参见three

的规则
class MemoryLeak {
   public:
    ~MemoryLeak() {
        delete problem_map;
    }
    MemoryLeak(const MemoryLeak& ) = delete;
    MemoryLeak& operator=(const MemoryLeak& ) = delete;
    MemoryLeak(std::vector<std::string>& inp) {
        int i = 0;
        problem_map = new std::map<std::string, int>;
        for (std::string& s : inp) {
           (*problem_map)[s] = i++; 
        }
    }
    std::map<std::string, int>* problem_map;
};

2)不存储指针,但存储地图

class MemoryLeak {
   public:
    MemoryLeak(std::vector<std::string>& inp) {
        int i = 0;
        for (std::string& s : inp) {
            problem_map[s] = i++;
        }
    }
    std::map<std::string, int> problem_map;
};