【问题标题】:Delete pointer in a map<int,A*>删除地图中的指针<int,A*>
【发布时间】:2026-01-30 13:40:01
【问题描述】:

基本上 B 是一个对象,A 是一个对象管理器,对于创建的每个对象,都会在 m_myMap 中执行一个新条目,以便跟踪对象的数量并能够获取该对象的指针。

我的问题是:我是否必须在 A 的析构函数中删除 m_myMap 中 B 的指针,或者如果 m_myMap 被自动销毁,是否不会出现内存泄漏?

啊哈:

#ifndef A_H
#define A_H

#include "B.h"

class B;
class A
{
    public:
        A();
        ~A();
        int addB(B* myBPointer);
    private:
        std::map<int,B*> m_myMap;
}

#endif

B.h:

#ifndef B_H
#define B_H

#include "A.h"

class A;
class B
{
    public:
        B(A* givenA);
        ~B();
    private:
        A *m_myA;
        int m_id;
}

#enfif

B.cpp:

B::B(A* givenA)
{
    m_myA = givenA;
    m_id = m_myA->addB(this);
}
B::~B(){} // nothing here because m_myA is coming from another class and is destroyed in that class

A.cpp:

A::A();

A::~A()
{
    for(std::map<int,B*>::iterator it = m_myMap.begin();it != m_myMap.end();++it)
        delete it->second;// the program crashes
}

int A::addB(B* myBPointer)
{
    m_myMap.insert(std::pair<int,B*>(m_myMap.size(),myBPointer));
    return m_myMap.size()-1;
}

C.cpp 和 C.h:

#ifndef C_H
#define C_H

#include "A.h"
class C
{
    public:
        C();
        void myFunction();
    private:
        A* my_A;
}

#endif

C::C()
{
    my_A = new A;
}

void C::myFunction()
{
    B myObject(my_A);
}

【问题讨论】:

  • 您是否测试过它在哪个循环迭代上崩溃?
  • m_myMap 是一个指针,但您的示例未显示您分配地图的位置。要么你没有发布一个完整的例子,要么问题可能是你没有首先分配地图。
  • 请停止使用 sn-ps。我已经删除了一次。他们在这里完全没有意义。单击“运行代码 sn-p”,看看你得到了什么。这就是你所追求的吗?
  • 抱歉,sn-ps 我无法将代码放入帖子中。

标签: c++ pointers dictionary this delete-operator


【解决方案1】:

一个问题是这样的:

m_myMap->erase(it);

使it 无效,因此之后您无法安全地使用它。一般来说,要在迭代容器时擦除元素,请将循环构造为

for (auto it = map.begin(); it != map.end(); /* don't increment here*/) {
    delete it->second;
    it = map.erase(it);  // update here
}

在这种情况下,由于您将要销毁地图,因此无需擦除每个元素,只需删除它们指向的对象即可。

您也没有关注Rule of Three,因此您可能会意外复制这些对象,最终导致两个人试图删除同一个对象。绝对没有理由动态分配地图,所以用对象成员替换它

std::map<int,B*> map;

仍然存在一个问题,即复制它会给出两个指向相同B 对象的映射。如果您没有充分的理由进行动态分配,请将对象本身存储在映射中:

std::map<int,B> map;

如果您确实需要动态分配(可能因为B 是一个基类,而实际对象可能是各种派生类型),那么要么使用智能指针(std::unique_ptr 可能适合),要么非常小心你如何处理原始指针。

一般来说,除非你真的需要,否则不要使用指针或new

【讨论】:

  • 我认为没有必要在循环中删除迭代器:它会导致树重新平衡,这只是浪费。地图将在循环结束后立即删除。
  • @roman-kashitsyn:没错,我没有详细阅读代码。我会添加一个注释。