使用静态 std::set 来管理类的所有实例的资源是否有目的?

问题描述

我继承了一些正在重构的代码,并且遇到了一些我不确定意图的东西。许多(或多或少)类认使用以下模式,似乎内存管理旨在使用静态 std::set 处理。

class A
{
public:
    A()
    { 
        B_ = new B();
        All_A.insert(this);
    }

    ~A(){ delete B_; }

    static void DestructAll_A()
    {
        for (std::set<A*>::iterator Itr = All_A.begin(); Itr != All_A.end(); ++Itr) 
        {
            A* Obj = *Itr;
            delete Obj;
        }

        All_A.clear();
    };

    static std::set<A*> All_A;

    B* B_;
}

我最初的想法是这是不好的做法。据我所知,如何使用类以这种方式拥有它没有明显的优势。 。此外,DestructAll_A() 不调用 A 的析构函数,因此除非事先调用 A 的析构函数,否则 B 永远不会被删除,这会产生对操作顺序的依赖,我发现这令人困惑(尽管我认为这可能是在 DestructAll_A()) 内完成。最后,我不清楚静态和动态构造的 A 实例将如何区分(使用 new)。

我错过了什么吗?使用这种模式的一般目的或优势是什么?提前致谢。

解决方法

useEffect(() => { const fetchItems = async () => { setIsLoading(true) const result = await axios( `../../../static/movie-reviews.json?name=${query}` ) 不调用 A 的析构函数

是的。 DestructAll_A() 的类型为 Obj,因此 A* 将调用 delete Obj 析构函数。对于未使用标量 A::~A() 分配的任何实例,这是未定义的行为。

最后,我不清楚如何区分静态和动态构造的 A 实例(使用 new)。

它不会尝试区分...除非与标量动态分配一起使用,否则绝不能使用此类。

,

我认为这是实现“穷人的垃圾收集”的尝试。这是在批处理情况下的工作方式:

  • 您获得了一批新作品,并开始处理
  • 你边走边分配内存,忽略释放它的需要
  • 批处理结束后,您可以调用 DestructAll_XYZ 来清理混乱
  • 您的系统已准备好进行下一批

这种方法又快又脏,所以我肯定会建议在某个时候清理它。至少我会摆脱静态集合,用更可控的东西代替它们 - 例如,BatchMemoryContext 包含所有相关集合。通过这种方式,您可以严格控制对象的生命周期,并避免可能出现的并发问题。

,

在评论 OP 中询问“是否有可能以某种方式隐式调用 DestructAll_A()?”

不是真正隐含的方式,而是几乎,以下可以解决问题:

Data: tensor([[ 2,2],...
        [ 1,10]])
Lengths: tensor([ 4,10])