避免C+中的内存泄漏+;班 我用下面的头文件定义了C++类: class EarleyParser { public: EarleyParser(); virtual ~EarleyParser(); void initialize( string filePath, bool probabilityParse ); private: bool probabilityParser; typedef unordered_map< string, list<Production>* > productionHashTable; productionHashTable earlyHashTable; };

避免C+中的内存泄漏+;班 我用下面的头文件定义了C++类: class EarleyParser { public: EarleyParser(); virtual ~EarleyParser(); void initialize( string filePath, bool probabilityParse ); private: bool probabilityParser; typedef unordered_map< string, list<Production>* > productionHashTable; productionHashTable earlyHashTable; };,c++,pointers,memory-leaks,unordered-map,delete-operator,C++,Pointers,Memory Leaks,Unordered Map,Delete Operator,如果要存储指向地图中任何内容的指针,则必须手动浏览地图并删除每个指针。通常在类中,您会坚持使用RAII(资源获取是初始化),在构造函数中构造东西,在析构函数中销毁 但是,指向容器的指针不是一个好主意。你为什么需要一个指针?使用指向列表的指针试图解决什么问题 使用像std::unique_ptr这样的智能指针比原始指针好得多。原始指针应该是最后的手段,而不是当你想不出更好的方法时,第一件要抓到的东西。如果你要在地图中存储指向任何东西的指针,你必须手动浏览地图并删除每个指针。通常在类中,您会坚持使用

如果要存储指向地图中任何内容的指针,则必须手动浏览地图并删除每个指针。通常在类中,您会坚持使用RAII(资源获取是初始化),在构造函数中构造东西,在析构函数中销毁

但是,指向容器的指针不是一个好主意。你为什么需要一个指针?使用指向
列表的指针试图解决什么问题


使用像
std::unique_ptr
这样的智能指针比原始指针好得多。原始指针应该是最后的手段,而不是当你想不出更好的方法时,第一件要抓到的东西。

如果你要在地图中存储指向任何东西的指针,你必须手动浏览地图并删除每个指针。通常在类中,您会坚持使用RAII(资源获取是初始化),在构造函数中构造东西,在析构函数中销毁

但是,指向容器的指针不是一个好主意。你为什么需要一个指针?使用指向
列表的指针试图解决什么问题

使用像
std::unique_ptr
这样的智能指针比原始指针好得多。原始指针应该是最后的手段,而不是当你想不出更好的东西时,第一件要抓住的东西。

使用:

typedef unordered_map< string, std::unique_ptr<list<Production> > > productionHashTable;
typedef无序映射productionHashTable;
相反。这样,您就不必担心管理内存。

使用:

typedef unordered_map< string, std::unique_ptr<list<Production> > > productionHashTable;
typedef无序映射productionHashTable;

相反。这样,您就不必担心内存管理。

编译器合成析构函数不会删除您放在映射中的动态分配列表,因此您必须自己完成。在这种情况下,您只需迭代地图并删除每个元素的
second
成员:

EarleyParser::~EarleyParser() {
  for ( productionHashTable::iterator i = earlyHashTable.begin(); i != earlyHashTable.end(); ++i )
    delete i->second;
}
更好的方法是在地图中放置列表,而不是指向列表的指针。在这种情况下,编译器将自动处理销毁,如下所示:

typedef unordered_map< string, list<Production> > productionHashTable;
typedef无序映射productionHashTable;

编译器合成析构函数不会删除您放在映射中的动态分配列表,因此您必须自己删除。在这种情况下,您只需迭代地图并删除每个元素的
second
成员:

EarleyParser::~EarleyParser() {
  for ( productionHashTable::iterator i = earlyHashTable.begin(); i != earlyHashTable.end(); ++i )
    delete i->second;
}
更好的方法是在地图中放置列表,而不是指向列表的指针。在这种情况下,编译器将自动处理销毁,如下所示:

typedef unordered_map< string, list<Production> > productionHashTable;
typedef无序映射productionHashTable;

您需要澄清谁拥有
列表
对象,这些对象由
EarlyParser
拥有。如果
EarlyParser
拥有它们,那么您需要释放这些资源。您可以通过迭代列表并在每个取消引用的迭代器上调用
delete
not
delete[]
)。或者您可以存储
unique\u ptr
。另一方面,最简单的解决方案是存储
list
,除非您确实有非常充分的理由来存储指针。

您需要澄清谁拥有
EarlyParser
拥有的
list
对象。如果
EarlyParser
拥有它们,那么您需要释放这些资源。您可以通过迭代列表并在每个取消引用的迭代器上调用
delete
not
delete[]
)。或者您可以存储
unique\u ptr
。另一方面,最简单的解决方案是存储
列表
,除非您确实有非常充分的理由来存储指针。

实际上调用它所拥有的对象的析构函数,这意味着将调用
列表
的析构函数。 请注意:

请注意,如果元素是指针,则指向的对象不会被销毁

这意味着,你必须自己清除这些记忆。是的,遍历容器并删除元素1by1就可以了。正如其他回答者提到的,保持这样的指针不是一个好主意。

实际上调用它所拥有的对象的析构函数,这意味着将调用
列表的析构函数。
请注意:

请注意,如果元素是指针,则指向的对象不会被销毁


这意味着,你必须自己清除这些记忆。是的,遍历容器并删除元素1by1就可以了。正如其他回答者所提到的,保持这样的指针不是一个好主意。

因为您使用的是指向
std::list
的原始指针,所以您必须在映射的生命周期中或在清理其析构函数中的
EarleyParser
对象时自己删除它

您可以在析构函数中使用如下内容:

for ( auto it = productionHashTable.begin();
      it != productionHashTable.end(); ++it )
{ 
    delete it->second;
}
productionHashTable.clear()

请注意,最后一行并不是绝对必要的,因为它将在
EarleyParser
对象被破坏时被清除,但很明显,在删除映射中的值后,不能使用它们

由于您使用的是指向
std::list
的原始指针,因此您必须在映射的生命周期中或在清理其析构函数中的
EarleyParser
对象时自己删除它

您可以在析构函数中使用如下内容:

for ( auto it = productionHashTable.begin();
      it != productionHashTable.end(); ++it )
{ 
    delete it->second;
}
productionHashTable.clear()

请注意,最后一行并不是绝对必要的,因为它将在
EarleyParser
对象被破坏时被清除,但很明显,在删除映射中的值后,不能使用它们

如果此对象拥有此列表,则应将其删除。使用共享指针而不是指向列表的原始指针-然后它将删除自身。如果我将其留给默认构造函数来释放分配的内存-您肯定是指析构函数?@Component10-of