如何将unique_ptr转换为原始指针?

13
我有一个函数,用于分配给定大小的缓冲区。在返回之前,缓冲区将被预处理/填充一些数据。这个预处理可能会返回false来表示该缓冲区未被正确处理。因此,我想在这个缓冲区上应用RAII以避免提前返回而不删除它。
通常情况下,我使用unique_ptr来帮助我自动释放本地分配的对象。在这种情况下,我需要返回这个分配的对象(由unique_ptr拥有),并将所有权转移给调用者。但是编译器抱怨我无法将unique_ptr转换为T*,同时我std::move了unique_ptr。看起来unique_ptr只能移动到另一个unique_ptr中,而不能移动到裸指针中。
有没有办法将所有权从unique_ptr转移到原始指针?还是说unique_ptr不适用于这种情况?
bool PreProcess(int* v) { /* return nothing wrong? true: false; */ }

bool GetBuffer(int** ppRetBuf, int size)
{
    std::unique_ptr<int[]> buf(new (std::nothrow) int[size]());
    if(PreProcess(buf.get())
    {
        *ppRetBuf = std::move(buf); // Compiler complains:  
                                    // Error C2440 '=': cannot convert from 'std::unique_ptr<int [],std::default_delete<_Ty>>' to 'int *'
        return true;
    }
    return false; // No need to manually delete[] failure buffer
}

int main()
{
    int * buf = nullptr;
    GetBuffer(&buf, 100);
}

1
就我所见,std::unique_ptr 在这里并没有给你任何好处。最好一开始就使用原始指针。 - πάντα ῥεῖ
6
你有阅读过任何文档吗?我认为你需要使用std::unique_ptr::release函数。 - Blastfurnace
@Blastfurnace 是的...我确实没有仔细阅读描述文档。也许我认为Release就像IUnknown::Release()一样,所以我没有进一步检查unique_ptr::release是什么。谢谢! - Chen OT
1
我认为那个网站上的文档通常都很清晰简洁,是一个不错的资源,你可能会想将其加入书签。 - Blastfurnace
2个回答

13
如何将unique_ptr移动到原始指针?
这样做避免了在此处使用unique_ptr的任何好处。
您可以使用std :: unique_ptr :: release(),但是这样使用unique_ptr就毫无意义了。考虑返回一个unique_ptr。这样调用者知道他们拥有该指针,并且在停止使用它时,数组将被释放。否则,您必须记录调用者必须释放内存以及如何释放的文档。
如果这不是一种选择,则根本没有必要使用unique_ptr,除非您正在进行在构造数组和返回之间可能引发异常的操作并为简单起见而省略了它。

6
在使用release时,使用unique_ptr并不是毫无意义的。你可能正在处理需要原始指针的外部代码。在这种情况下,您可以在构造这些对象时使用unique_ptr。如果在将它们交给外部代码之前抛出任何异常,则仍会删除该对象。 - Aedoro
就像我说的那样,“除非您在构建数组和返回之间进行可能导致异常的操作,否则根本不需要使用unique_ptr ”。 @Aedoro - eerorika

7

由于ppRetBuf和buf是两种不同的数据类型,所以编译器会显示错误信息。

为了实现你想要的功能,你需要调用buf上的release函数。

*ppRetBuf = buf.release();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接