如果存储在指针映射中,是不是需要删除对象?

Posted

技术标签:

【中文标题】如果存储在指针映射中,是不是需要删除对象?【英文标题】:Do objects need to be deleted if stored in a map of pointers?如果存储在指针映射中,是否需要删除对象? 【发布时间】:2015-10-25 22:57:27 【问题描述】:

我开始掌握指针并避免内存泄漏...

不过我有一个问题...在开始之前,我没有使用 C++11,所以请不要回复有关智能指针的信息以及特定于 C++11 的信息...

我有以下代码...

class Test

public:
   Test(const int s_id, const std::string s_name) :
      id(s_id),
      name(s_name)
   

   ;
   const int GetID()
   
      return id;
   

private:
   const int id;
   const std::string name;
;

class TestCollection

public:
   void AddTest(Test& my_test)
   
      tests[my_test.GetID()] = &my_test;
   

   void RemoveTest(const int id)
   
      if (tests.find(id) != tests.end())
      
         tests.erase(id);
      
   
public:
   std::map<int, Test*> tests;
;

int _tmain(int argc, _TCHAR* argv[])

   TestCollection collection;
   Test my_test(0, "First Test");
   collection.AddTest(my_test);

   collection.RemoveTest(0);

    return 0;

我的问题是,当我调用 RemoveTest 时,我是否需要做任何其他事情来清除 my_test 中的内存?从而避免内存泄漏?

我知道当我使用 new 关键字时我需要调用 delete...但是在这种情况下我该怎么办?

垃圾收集器会自动清理它吗?

【问题讨论】:

这取决于对象的分配方式。但最好发布真实代码。 该代码实际上不会编译。 tests 只能存储指针,而您正在尝试存储引用。 你只需要delete你用new分配的对象。在其他对象上使用delete 是未定义的行为(我认为)。 @JonathanPotter 我已经更新了它,所以它可以编译... 好的,现在在您的示例中,您正在存储一个指向已在堆栈上分配的对象的指针。你不需要删除它,因为它会在作用域结束时自动销毁。请注意,删除它的不是map - 它只是在_tmain() 返回时自动销毁。但是这种模式的用处有限;存储指向基于堆栈的对象的指针是危险的,因为它可能导致使用悬空指针和未定义的行为。 【参考方案1】:

在示例中,collection 和 my_test 都分配在堆栈上。一旦作用域结束(从_tmain返回),内存就会被释放。

获取可能存在于变量范围之外的堆栈变量的指针将导致不可预知的行为。在这种情况下,如果集合获取对象并存储指针而不是副本。

【讨论】:

有什么替代方案?而是到处使用指针? 您可以让 TestCollection 类创建正在传递的对象的副本。此副本将驻留在堆中,并将使用新的分配。调用 Remove 时,您需要将其删除。调用者不需要使用指针。 我假设您询问的示例程序只是一个 sn-p。假设您有一个大型应用程序。您将拥有 100 种操作 TestCollection 对象的函数/方法。当这样的函数调用测试集合对象上的方法时,那将是该方法的调用者。如果您要存储指向调用者堆栈上分配的对象的指针,则这些指针仅在变量范围内有效。 [链接] (en.cppreference.com/w/cpp/language/scope)

以上是关于如果存储在指针映射中,是不是需要删除对象?的主要内容,如果未能解决你的问题,请参考以下文章

在具有自动存储持续时间的对象上使用智能指针

如果我在函数中使用指针来填充列表,我是不是必须在 C++ 中删除该函数末尾的指针?

数据结构01——线性表

为啥需要声明一个指针而不是一个对象?

如果已删除,如何从向量中删除对象

c ++:原始指针映射中的复制,删除和运算符=