使用静态 std::set 来管理 class 的所有实例的资源是否有目的?
Is there a purpose for using a static std::set to manage resources of all instances of a class?
我继承了一些我正在重构的代码,我遇到了一些我不确定意图的事情。许多(或多或少全部)类 已默认为以下模式,其中内存管理似乎旨在使用静态 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 的析构函数,因此 B 永远不会被删除,除非事先调用 A 的析构函数,这会产生对操作顺序的依赖,我觉得这很混乱(尽管我认为这可以在 DestructAll_A()) 内完成。最后,我不清楚如何区分静态构造与动态构造(使用 new)的 A 实例。
我错过了什么吗?使用这种模式的一般目的或优势是什么?提前致谢。
DestructAll_A()
does not call A's destructor
是的。 Obj
具有类型 A*
,因此 delete Obj
将调用 A::~A()
析构函数。对于未使用标量 new A()
.
分配的任何实例,这是未定义的行为
Lastly, it's unclear to me how it would be differentiated instances of A that were statically vs dynamically constructed (using new).
它不会尝试区分...此 class 绝不能使用,除非用于标量动态分配。
在评论 OP 中询问“DestructAll_A() 是否有可能以某种方式隐式调用?”
不是真正隐含的方式,但几乎可以做到以下几点:
class A_Cleaner
{
~A_Cleaner(){
A::DestructAll_A();
}
}
void Main()
{
A_Cleaner cleaner;
.... //your program
// just before reaching the end of main, cleaner dtor is called, so A::DestructAll_A() is called, even in case of exception;
}
我认为这是实施“穷人的垃圾收集”的尝试。以下是它在批处理情况下的工作方式:
- 您获得了一批新的工作,并开始处理
- 你在分配内存的同时忽略了释放它的需要
- 批处理结束后,您调用
DestructAll_XYZ
收拾残局
- 您的系统已为下一批做好准备
这种方法既快又脏,所以我肯定会建议在某个时候清理它。至少我会摆脱静态集,用更可控的东西代替它们——比如,BatchMemoryContext
中包含所有相关集。这样您就可以严格控制对象的生命周期,并避免可能出现的并发问题。
我继承了一些我正在重构的代码,我遇到了一些我不确定意图的事情。许多(或多或少全部)类 已默认为以下模式,其中内存管理似乎旨在使用静态 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 的析构函数,因此 B 永远不会被删除,除非事先调用 A 的析构函数,这会产生对操作顺序的依赖,我觉得这很混乱(尽管我认为这可以在 DestructAll_A()) 内完成。最后,我不清楚如何区分静态构造与动态构造(使用 new)的 A 实例。
我错过了什么吗?使用这种模式的一般目的或优势是什么?提前致谢。
DestructAll_A()
does not call A's destructor
是的。 Obj
具有类型 A*
,因此 delete Obj
将调用 A::~A()
析构函数。对于未使用标量 new A()
.
Lastly, it's unclear to me how it would be differentiated instances of A that were statically vs dynamically constructed (using new).
它不会尝试区分...此 class 绝不能使用,除非用于标量动态分配。
在评论 OP 中询问“DestructAll_A() 是否有可能以某种方式隐式调用?”
不是真正隐含的方式,但几乎可以做到以下几点:
class A_Cleaner
{
~A_Cleaner(){
A::DestructAll_A();
}
}
void Main()
{
A_Cleaner cleaner;
.... //your program
// just before reaching the end of main, cleaner dtor is called, so A::DestructAll_A() is called, even in case of exception;
}
我认为这是实施“穷人的垃圾收集”的尝试。以下是它在批处理情况下的工作方式:
- 您获得了一批新的工作,并开始处理
- 你在分配内存的同时忽略了释放它的需要
- 批处理结束后,您调用
DestructAll_XYZ
收拾残局 - 您的系统已为下一批做好准备
这种方法既快又脏,所以我肯定会建议在某个时候清理它。至少我会摆脱静态集,用更可控的东西代替它们——比如,BatchMemoryContext
中包含所有相关集。这样您就可以严格控制对象的生命周期,并避免可能出现的并发问题。