检测堆栈或堆分配
我有一个班,我希望能够设置一个标志,说如果它是堆分配,所以它可以适当清理后,而不是尝试删除自己,如果它在堆栈上。 问题是......我似乎无法同时重写new
和构造函数。 所以它从我的new
重载设置isHeapAllocated
标志,然后到我的构造函数重置标志。
void* String8::operator new(size_t size)
{
String8* string = (String8*)malloc(size);
if(string == null)
Exception("allocation fail : no free memory");
string->isHeapAllocated = true;
return string;
}
String8::String8()
{
isHeapAllocated = false;
}
所以new String8()
设置isHeapAllocated
标志,然后将其重置为false
。 有没有办法做到这一点?
它不会按预期工作:
新的运算符返回单元化内存给予构造函数。 你 - 正确地做String8* string = (String8*)malloc(size);
,但是*string
,在这个阶段还不是一个String8对象:它只是包含它的内存批量。
所以string->isHeapAllocated = true;
实际上在一个尚未构造的对象(即UB)内设置一个标志。
承认这一点不会影响操作系统的进程,所以程序不会崩溃(你写的内存已经属于你了,毕竟...),当你稍后再做一些像String8* ptr = new String8;
,在新的返回之后,String8 :: String8构造函数被调用,并且成员将独立于您在新运算符重载中执行的操作而重新设置为“false”。
管理C ++对象的惯用方式是由谁来分配负责解除分配。 (如果“谁”是堆栈,它只是按照定义来做)。
这是一个坏主意,但是这里有一种方法可以实现,它不会引发未定义的行为。
#include <iostream>
#include <memory>
#include <set>
using namespace std;
class C {
public:
void* operator new(size_t size) {
C* c = static_cast<C*>(::operator new(size));
heap_instances.insert(c);
return c;
}
C() : heap_allocated(heap_instances.find(this) != heap_instances.end()) {}
const bool heap_allocated;
private:
static set<const C*> heap_instances;
};
set<const C*> C::heap_instances;
int main(int argc, char** argv) {
cout << boolalpha;
C stack;
cout << stack.heap_allocated << 'n'; // false
C* heap_nozero = new C;
cout << heap_nozero->heap_allocated << 'n'; // true
delete heap_nozero;
C* heap_zero = new C();
cout << heap_zero->heap_allocated << 'n'; // true
delete heap_zero;
}
当你完成这些操作时,你可以从heap_instances
移除指针,如果你在多线程环境中运行,可以使用更适合的容器。 但是,我不会建议你真的这样做 - 基于分配的决定行为不是一个对象应该做的事情。
我能想到的唯一正当理由是为了delete this
。 尽管在对象自杀后小心不要访问成员是安全的,但让对象管理其他对象的生命周期通常更为安全。
请注意,如果构造器分配在堆栈或堆上,并且没有办法让对象检测它是在堆栈还是堆中分配的。
要在堆栈中创建一个对象,不要使用像这样的任何内存分配函数
String8 myString;
在堆上创建它
String8 *myString = new String8();
请注意,不必再使用对象后,您必须手动进行清理。
对于绑定到堆栈范围的堆对象的使用,您可以查看由c ++程序强烈使用的RAII原则(请参阅此处以更好地解释堆分配和堆栈分配的差异)。
链接地址: http://www.djcxy.com/p/96545.html