删除与其他类共享的指针

时间:2017-09-04 11:30:01

标签: c++ pointers memory-management shared-ptr

我使用类之间共享的指针在c ++中遇到内存释放问题。

一个例子:

我的顶点定义为:

@Component
public class FtpServer {

    @Value("${ftp.port}")
    private int port;

    @PostConstruct
    public void init() {
        System.out.println(this.port);
    }

}

正方形定义为:

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

那么问题是什么?如果两个方格共享一个顶点,我的程序崩溃,因为它试图删除一个不再存在的指针。 我怎么解决这个问题?

3 个答案:

答案 0 :(得分:5)

在我看来,你是用C ++编写的,具有类似Java的思维模式。只包含两个Vertex的{​​{1}}个对象(例如你的X和Y组件)更好地存储在堆栈中,没有指针间接。所以,我会像这样声明double类:

Square

如果您想要一种参考机制,而不是嵌入class Square{ ... Vertex a; Vertex b; Vertex c; Vertex d; }; 对象,您可以将顶点存储在Vertex数组中,并存储在std::vector<Vertex>类整数中索引到数组中的顶点位置。

如果确实希望使用指针共享所有权语义,请考虑使用智能指针,如Square。当引用计数达到零时,没有明确的std::shared_ptrdelete自动释放内存。

在这种情况下,将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>创建智能指针。

答案 1 :(得分:2)

除非你有充分的理由这样做,否则你不应该在Modern C ++中手动分配内存。如果您的Square类要为Vertex个实例的共享所有权建模,那么您应该使用std::shared_ptr

class Square{
    // ...
    std::shared_ptr<Vertex> a, b, c, d;
}

但是我建议你重新考虑使用动态内存分配来简化和轻量级Vertex

答案 2 :(得分:0)

如果您使用遗留代码并且无法将原始指针更改为共享指针,或者您不能简单地复制顶点(您想要引用原始对象),那么不要删除Square析构函数中的顶点,并且可能使用对顶点的引用而不是指针。

您已经在Square对象之外管理Vertexes的分配,因此请确保仅在所有正方形消失后才释放顶点。

代码流程如下所示:

  • 分配了所有顶点:容器跟踪所有顶点
  • 在多个对象中使用顶点,可能通过对它们的引用
  • 当所有使用顶点的对象消失后,释放容器中的所有顶点(如果容器存储Vertex对象而不是指针,则只需清除容器)