【问题标题】:How can I avoid a memory leak when initializing a map in the constructor of a class?在类的构造函数中初始化映射时如何避免内存泄漏?
【发布时间】:2019-09-29 03:23:47
【问题描述】:

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

【问题讨论】:

  • 您认为为什么需要指向地图的指针?
  • 感谢@NeilButterworth 的回复!我稍后会(在我在这里没有提到的代码中)将地图的一部分传递给该类的另一个实例而不复制数据。
  • @fabian 需要指针的日子已经一去不复返了。由于移动语义,您可以将实例传递给具有恒定时间复杂度的另一个所有者,而无需复制它。编辑:即使您的特定用例需要指针,也更喜欢像unique_ptr 这样的智能指针。
  • 不要使用原始指针和new,有更好的方法来做任何你想做的事情
  • 感谢您的评论,@FrançoisAndrieux!我对这些概念有模糊的了解,但我目前正在通过Accelerated C++ 工作,并且想在学习新概念之前很好地理解这些材料。

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


【解决方案1】:

对于段错误

您的指针 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;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-30
    • 2021-11-10
    • 2012-07-29
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    相关资源
    最近更新 更多