13

I have a function that is used to allocate a buffer with given size. The buffer will be preprocess/filled some data before return. This preprocess may return false to represent this buffer is not processed right. So I want to apply RAII on this buffer to avoid early return without delete[] it.

Usually I use unique_ptr to help me to auto release the local allocated object. In this case I need to return this allocated object (Owned by unique_ptr) and transfer the ownership to caller. But the compiler complains that I cannot convert unique_ptr<T[]> to T* while I std::move the unique_ptr. It looks like unique_ptr can only be moved to another unique_ptr instead of raw pointer.

Is any way to transfer the ownership from unique_ptr to a raw pointer? Or just the unique_ptr is not suitable for this case?

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);
}
Itay Sela
  • 942
  • 9
  • 26
Chen OT
  • 3,486
  • 2
  • 24
  • 46
  • 1
    As far I can see the `std::unique_ptr` doesn't give you any benefit here. Just use a raw pointer in first place then. – πάντα ῥεῖ Oct 22 '15 at 06:56
  • 6
    Do you ever read any documentation? I think you want [`std::unique_ptr::release`](http://en.cppreference.com/w/cpp/memory/unique_ptr/release) – Blastfurnace Oct 22 '15 at 06:56
  • @Blastfurnace Yeah... I does not read the description documentation carefully indeed. Maybe I though the Release is like IUnknown::Release() so that I does not check unique_ptr::release further what it is. Thanks! – Chen OT Oct 22 '15 at 07:06
  • 1
    I think the documentation on that website is generally clear and direct, it's a good resource and you might want to bookmark it. – Blastfurnace Oct 22 '15 at 07:09

2 Answers2

13

How to move unique_ptr to raw pointer?

Well, that's one way of avoiding any benefits of using unique_ptr here.

You can use std::unique_ptr::release() but then the use of unique_ptr is pointless in the first place. Consider returning a unique_ptr instead. That way the caller knows that they own the pointer and the array will be freed when they stop using it. Otherwise you'd have to document that the caller must deallocate and how they must do it.

If that's not an option, then there's no use for unique_ptr at all unless you are doing something that might throw between constructing the array and returning it and left it out for simplicity.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 6
    Using `unique_ptr` is not pointless in combination with release. You might be dealing with external code that wants raw pointers. Then you can use a `unique_ptr` during construction of these objects. If any exceptions are thrown before you hand them to the external code the object is then still deleted. – Aedoro Jun 09 '20 at 10:05
  • @Aedoro As I said, "there's no use for unique_ptr at all **unless you are doing something that might throw between constructing the array and returning it**" – eerorika Jun 09 '20 at 10:22
7

Since ppRetBuf and buf are two different data types the compiler gives the error message for that.

In order to do what you want to do you need to call release on buf

*ppRetBuf = buf.release();
AndersK
  • 35,813
  • 6
  • 60
  • 86