我如何知道一个对象是否在堆上分配使用new

How do I know if an object is allocated on the heap using new?

本文关键字:分配 new 何知道 一个对象 是否      更新时间:2023-10-16

我想知道是否有任何标准库函数或其他技巧,通过它我可以查询指针是否由应用程序分配。实际上我想做下面的事情....

假设我有一个函数:

void DoSomeThing(SomeObject* pObj);
要调用这个函数,我们通常有如下两种选择:
//The first method using stack
SomeObject ObjLocal(Arg1,Arg2);
DoSomething(&ObjLocal);
//The second method using heap
SomeObject* ObjUserAllocated=new SomeObj(Arg1,Arg2);
DoSomeThing(ObjUserAllocated);
//But I like to use code like below (saves me some typing)
DoSomeThing(new SomeObject(Arg1,Arg2));

但是第三种方法的问题是-内存的释放现在是被调用方法的责任,这里我卡住了,因为我不确定对象是否由应用程序分配。

我把这个问题贴在这里,甚至没有谷歌它,因为我很好奇,如果我得到一个干净的解决方案,这将是一个伟大的奖励我…很抱歉。

如果不可能确定一个对象是否在堆上,那么你的大师会建议我如何实现我想要的?

没有可移植的方法来确定指针是否指向动态分配的对象,没有

选择一种解决方案而不是另一种解决方案是一个非常糟糕的理由。在您提供的三个选项中,第一个显然是最好的,因为它依赖于自动生命周期管理。

也就是说,如果你真的要创建一个对象只是为了传递给DoSomeThing函数,最好的选择可能是让DoSomeThing通过值(或通过常量引用)获取SomeObject;那么你就完全不需要处理指针了

我如何知道一个对象是否在堆上使用new或Malloc()由当前模块?

你不能。给定一个指针值,没有可移植/可靠的方法来确定它是由new分配的,还是由malloc()分配的,或者它是否指向自由存储上的某个对象(正如您的第一个方法所示,传递的指针实际上可能指向自动存储上的对象)。它甚至可以指向数组中的一个元素。DoSomeThing()根本看不出来。

处理这个问题的方法是让函数的用户自己管理内存。第一种方法通常用于类似的情况,因为堆栈分配是自动的。例如,很多Windows API(大部分是C API)是这样做的,类似于你的第一个方法:

WNDCLASSEX wndcls;
// Fill wndcls structure
::RegisterClassEx(&wndcls);

这里RegisterClassEx()不关心我的WNDCLASSEX是在堆栈上,在自由存储上,还是作为数组的一部分,只要我传递一个指针,实际上指向WNDCLASSEX。所以你的第一种方法确实是在现实世界中处理它的首选方法。


如果不需要C语言支持,也可以使用引用:

void DoSomeThing(SomeObject& out) {}

这种方法的一个优点是用户不能传递一个NULL指针,所以你不必检查它。如果DoSomeThing()没有修改SomeObject,那么更好的方法是使用const引用:

void DoSomeThing(const SomeObject& out) {}

这个签名的好处是它允许这种调用工作:

DoSomeThing(SomeObject(Arg1,Arg2));

所以你得到了你想要的"少打字",而不用担心内存管理。

首先让我说,你几乎肯定设计得很糟糕,才会出现这种情况。

也就是说,你可以用一些shared_ptr滥用来做到这一点:

void DoSomeThing(std::shared_ptr<SomeObject> pObj);
SomeObject obj(arg1, arg2);
DoSomeThing(new SomeObject(arg1, arg2));
DoSomeThing(std::shared_ptr<SomeObject>(&obj, [](SomeObject*){})); // Empty deleter written as C++11 lambda (could write out the functor elsewhere if not using C++11)