我想在类的构造函数中初始化一个(指向 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 )时,程序编译但似乎发生了内存泄漏。有人可以告诉我我做错了什么吗?更合适的构造函数会是什么样子?

最佳答案

对于 段错误 :

您的指针 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)不存储指针,而是存储 map
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;
};

关于c++ - 在类的构造函数中初始化映射时如何避免内存泄漏?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56090788/

10-11 23:21
查看更多