基本上B是一个对象而A是一个对象管理器,对于每个创建的对象,将在m_myMap中执行一个新的条目,以便跟踪对象的数量并能够获得该对象的指针。
我的问题是:我是否必须在A&#39的析构函数中删除m_myMap中的B指针,否则如果m_myMap被自动销毁,会不会出现内存泄漏?
A.H:
#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);
}
答案 0 :(得分: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
。