如何分辨另一个物体死亡的对象

How to tell the object of the death of another object?

本文关键字:对象 另一个      更新时间:2023-10-16

在我的工作中,我遇到了一个错误,可以描述如下。有两个类,A类和B类:

class A
{
public:
    void print(){}
};  
class B
{
    A* a;
public:
    void init(A* _a) {
        a = _a;
    }
    void PrintWithA()
    {
        a->print();
    }
};
A* a;
B* b;
b->init(a);
// some code .....
delete a;        // line 1
a = NULL;
// some code .....
b->PrintWithA(); // line 2
对象"

b"对对象"a"的状态一无所知。 在第 1 行中,"a"对象已被删除,但在第 2 行,我们继续使用它。当有很多代码时,很容易犯这样的错误。我的问题是以下 - 使用哪种方法来避免一些错误?我想我可以使用观察者模式 - 但我认为这是不合理的昂贵解决方案。谢谢。

你应该使用弱 ptr (http://en.cppreference.com/w/cpp/memory/weak_ptr)

基本上你可以提供 B 类的弱 PTR 为 A。

每当需要访问 A 时,您可以尝试锁定弱 ptr 以查看它是否仍然有效。

#include <memory>
class A
{
public:
    void print(){}
};  
class B
{
    std::weak_ptr<A> a;
public:
    void init(std::weak_ptr<A> _a) {
        a = _a;
    }
    void PrintWithA()
    {
        if (auto spt = a.lock()) { 
            spt->print();
        }
    }
};
int main()
{
    std::shared_ptr<A> a = std::make_shared<A>();
    std::unique_ptr<B> b = std::make_unique<B>();
    b->init(a);
    // some code .....
    a = nullptr;
    // some code .....
    b->PrintWithA(); // line 2
    return 0;
}

为了防止这种情况,要么 B 需要在构造对象 B 时获得 A 生存期的所有权,要么您需要对 A 引用进行计数。

C++11 我认为有一个共享指针的概念,它维护引用,如果有人有引用,将防止对象 A 被删除。 见std::shared_ptr

如果您不使用 C++11,则boost::shared_ptr基本上可以执行相同的操作。 但是你需要我个人不喜欢使用的提升库,但这取决于你。

像这样使用它们:

typedef std::shared_ptr<A> A_ptr;
A_ptr a = new A();
class B
{
    A_ptr a;
public:
    void B(A_ptr _a) {
        a = _a;
    }
    void PrintWithA()
    {
        a->print();
    }
};

否则你可以自己把一些东西放在一起。 大致如下:

class A
{
public:
    A(){
      ref_count = 1;
    }
    void print(){}
    void grab() {
      ref_count++;
    }
    void release() {
      ref_count--;
      if (ref_count <= 0)
        ~A();
    }
private:
    int ref_count;
    ~A(){
      delete this;
    }
}; 

在 B 中,您将分配指针并调用 grab();

而不是调用删除(这不起作用,因为它是私有的),你会调用指针上的 a->release()。

现在这不是特别好,因为你不能使用这种形式:

A a;

所以这并不理想。 但是,如果您使用的是某些没有shared_ptr的编译器,并且您不介意限制,则可以使用它或它的一种形式。 通常,使用shared_ptr

首先,说A* a;的行可能应该A* a = new A; .

在 c++ 中,您需要显式编码此意识,它不会自动完成。

您可以做的一件事是检查_aPrintWithA 中是否为 NULL,但如果您确保在delete[]后始终将指针设置为 NULL,这将不起作用(您已经这样做了)

相关文章: