Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use unique_ptr with operator new

I am allocating a piece of scratch memory with input size, and I'd like to use a unique_ptr to track proper lifetime without having to explicitly worry about freeing it myself. This is what I came up with:

{
    std::unique_ptr<BYTE> sp;
    sp.reset(reinterpret_cast<BYTE*>(operator new (100)));
}

I had to use a BYTE since MSVC won't compile with std::unique_ptr<void>. From my testing, the new and delete operators are called as expected. Since this is a bit of an uncommon usage (i.e. using operator new explicitly), I wanted to check that there's nothing wrong with this? And whether there's any alternatives that may be better/cleaner?

like image 649
lancery Avatar asked Jun 25 '14 02:06

lancery


People also ask

Can you assign to a unique_ptr?

It can be assigned: class owner { std::unique_ptr<someObject> owned; public: owner() { owned=std::unique_ptr<someObject>(new someObject()); } };

Can unique_ptr be copied?

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.

When should we use unique_ptr?

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

How is unique_ptr implemented in C++?

unique_ptr allows only one owner of the underlying pointer while shared_ptr is a reference-counted smart pointer. In this implementation, the developer doesn't need to explicitly delete the allocated memory towards the end of the function.


1 Answers

Assuming you want to dynamically allocate an array using new[], you must use the unique_ptr partial specialization for array types. Otherwise a unique_ptr will call delete on the array, instead of delete[], when it goes out of scope, which would be undefined behavior. Use this:

std::unique_ptr<BYTE[]> sp(new BYTE[100]);

And if you're using VS2013, you can even avoid the call to new by using make_unique.

auto sp = make_unique<BYTE[]>(100);

Note that the make_unique version will zero-initialize the array, while the first version won't.


If you really intended to use operator new, then you'll need to provide a custom deleter that will call operator delete to free the memory.

std::unique_ptr<BYTE, void(*)(BYTE *)> sp(static_cast<BYTE *>(::operator new(100)),
                                          [](BYTE *p) { ::operator delete(p);} );
like image 96
Praetorian Avatar answered Oct 05 '22 23:10

Praetorian