我在使用类之间共享的指针的c++中存在内存释放问题。
一个例子:
我的顶点定义为:
class Vertex{
double x;
double y;
}
正方形定义为:
class Square{
Square(Vertex* a, Vertex* b, Vertex* c, Vertex* d);
~Square(); // destructor
Vertex* a;
Vertex* b;
Vertex* c;
Vertex* d;
}
我的析构函数是这样实现的:
Square::~Square(){
delete a;
delete b;
delete c;
delete d;
}
我的正方形存储在
std::vector<Square*> squares
中,因此为了清理我的所有内存,我这样做:for(unsigned int i = 0; i < squares.size(); i++){
delete(squares.at(i));
}
那是什么问题呢?如果两个正方形共享一个顶点,则我的程序会崩溃,因为它试图删除不再存在的指针。
我怎么解决这个问题?
最佳答案
在我看来,您正在以类似Java的思维方式在C++中进行编码。仅包含两个Vertex
的double
对象(例如您的情况下的X和Y分量)最好存储在堆栈中,而无需指针间接寻址。因此,我将像这样声明Square
类:
class Square{
...
Vertex a;
Vertex b;
Vertex c;
Vertex d;
};
如果要代替某种形式的引用机制来嵌入
Vertex
对象,则可以将顶点存储在std::vector<Vertex>
数组中,并在Square
类中存储指向数组顶点位置的整数索引。如果您确实希望与指针共享所有权语义,那么可以考虑使用智能指针,例如
std::shared_ptr
。没有明确的delete
:引用计数达到零时,shared_ptr
将自动释放内存。在这种情况下,将原始的拥有指针数据成员的
Vertex*
替换为shared_ptr<Vertex>
类内的Square
。此外,从Square
类中删除析构函数代码,因为shared_ptr
知道如何删除自身。在
Square
类的构造函数中,您可以按值获取shared_ptr<Vertex>
智能指针,并在相应的数据成员中对它们进行std::move
,例如:Square::Square(
std::shared_ptr<Vertex> pa,
std::shared_ptr<Vertex> pb,
std::shared_ptr<Vertex> pc
)
: a{std::move(pa)}
, b{std::move(pb)}
, c{std::move(pc)}
{}
还要用
vector<Square*>
替换vector<shared_ptr<Square>>
(但是,您确定更简单的vector<Square>
不能很好地为您服务吗?),然后使用std::make_shared
创建智能指针。