从函数返回堆分配的指针是否不好?

问题描述

| 在“ 0”之前,从函数返回堆分配的指针是否被认为是不好的做法,因为将要求调用者记住“ 1”该对象? 还是被认为是“正常”?     

解决方法

        我不认为这是一个坏习惯,只要您的API还提供了等效的
XXX_free
(或whatever3ѭ,
XXX_clearup
或其他功能),客户端代码在使用指针结束时便可以调用。 这样一来,您就拥有了一个一致,对称的API,从某种意义上说,将堆对象生命周期的责任保持在一个地方。 这种方法也适用于更复杂的资源释放。例如,如果返回的指针指向动态分配的结构,该结构又具有指向动态分配的内存的成员,则可以从客户端代码中隐藏/抽象整个清理过程。     ,        您已标记问题C。在C中,这很常见,例如
fopen
返回
FILE *
,稍后必须通过调用
fclose
将其释放。 如果您打算将其标记为C ++,那么它会更复杂。较旧的代码库(1990年代中期或更早)经常围绕裸露的对象指针传递。整个商业支持的库都基于该模式(Borland的OWL,Microsoft MFC)。     ,        如果需要这样做,通常的做法是提供自己的“ free”函数,该函数将分配的指针释放出来。这样可以防止用户使用会破坏内存的不兼容的免费实现。     ,        您将找到这两种方法的示例:分配内存并返回指针的函数,或者接受指向已分配空间的指针的函数。 只要清楚地记录和遵循了该界面,这两种方法的正面和负面都有。例如,正如许多其他人提到的那样,提供分配功能的库通常应提供删除功能。当您(客户端)不知道在该精美功能中使用了哪种方法分配内存时,您(客户端)也不知道应使用哪种方法来销毁它。 另一方面,当您需要担心存储分配,将其传递给可能执行或可能无法执行预期工作,然后确定该存储是否仍然相关等时,逻辑可能会更加复杂。使用内存,隐藏分配细节也可以帮助封装一些优化。 简短的答案是:取决于您。真正错误的方法是选择某些东西,或者界面中的内容不一致或不清楚。     ,        它曾经是而且仍然很常见,因为它几乎是处理针对某些操作系统上的不同运行时构建的库的唯一方法。例如,在Windows上,通常只有在这些库负责其自身所有的内存管理(包括对象的分配和处置)时,才能在单个可执行文件中共享多个VC ++运行时库。
shared_ptr
和类似的工具实际上可能在这种情况下引起问题。 话虽这么说,通常情况下,函数名称和/或文档(正确完成后)将使情况显而易见。通常有一个对应的DeleteXXX()函数来处理免费呼叫。     ,        通常,您只会从显式的create_blah()函数返回一个指针 更常见的是传入一个指针(指向一个指针),如果该指针为null,则由函数分配。     ,实际上,更好的习惯用法(由COM接口使用)是要求在函数调用之前在调用方创建指针,并编写一个接受双指针的函数。 例如:     HRESULT CreateDevice(       [in] UINT适配器,       [in] D3DDEVTYPE设备类型,       [在] HWND hFocusWindow中,       [in] DWORD BehaviorFlags,       [输入,输出] D3DPRESENT_PARAMETERS * pPresentationParameters,       [out,retval] IDirect3DDevice9 ** ppReturnedDeviceInterface     ); 因此,调用者负责创建指针并调用分配函数,因此更有可能记得调用释放函数(在COM \的情况下,需要在COM对象上调用
->Release()
方法) 但是我认为采用创建/销毁功能,并与传递双指针结合使用,是一种提醒接收者使用堆对象后清除堆分配对象的更好方法。 我同意奥利(Oli)的观点,即Create / Destroy函数的对称性要强得多,并且Destroy函数的存在应该使API用户相信,他从Create函数获得的这些对象将不会自己消失,并且(销毁fcns)需要被调用。