我怎么知道是否使用new在堆上分配了一个对象?

时间:2012-01-01 05:53:01

标签: c++ stack heap

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

Suupose我有一个函数:

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));

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

我在这里发布了这个问题,甚至没有用谷歌搜索它,因为我对它很好奇,如果我得到一个干净的解决方案,对我来说是一个很好的奖励......很抱歉。

如果无法确定对象是否在堆上,那么大师会如何建议我实现我想要的?

3 个答案:

答案 0 :(得分:11)

没有可移植的方法来确定指针是否引用具有动态分配的对象,编号

它“为我节省了一些打字”是一个非常糟糕的理由选择一个问题的解决方案而不是另一个。在您提出的三个选项中,第一个显然是最好的,因为它依赖于自动生命周期管理。

也就是说,如果你真的要创建一个对象只是为了传递给DoSomeThing函数,那么最好的选择可能是DoSomeThingSomeObject的值(或者是const) -参考);那么你根本不需要处理指针。

答案 1 :(得分:3)

  

我怎么知道是否使用new或者在堆上分配了一个对象   malloc()由当前模块?

你做不到。只给出一个指针值,没有可移植/可靠的方法来确定它是由new分配,malloc(),还是它甚至指向免费商店的东西(正如你的第一个方法所示) ,传递的指针实际上可能指向自动存储上的对象)。它甚至可能指向数组中的元素。 DoSomeThing()无法分辨。

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

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

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


如果不需要C支持,您还可以使用引用:

void DoSomeThing(SomeObject& out) {}

这种方法的一个优点是用户无法传递NULL指针,因此您无需检查它。如果DoSomeThing()没有修改SomeObject,那么更好的方法是使用const引用:

void DoSomeThing(const SomeObject& out) {}

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

DoSomeThing(SomeObject(Arg1,Arg2));

因此,您可以在不担心内存管理的情况下获得“减少打字”。

答案 2 :(得分:-1)

首先让我说你几乎肯定会设计一些不好的东西来应对这种情况。

也就是说,你可以通过一些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)