11

To get a void * from a function in C I would do something like this (very basic example):

void *get_ptr(size_t size)
{
    void *ptr = malloc(size);
    return ptr;
}

How do I achieve the same result when using std::unique_ptr<>?

ZeppRock
  • 988
  • 1
  • 10
  • 22
  • https://stackoverflow.com/questions/4316727/returning-unique-ptr-from-functions – dragosht Jan 16 '20 at 08:59
  • 1
    Please explain what problem you're having with doing it. – molbdnilo Jan 16 '20 at 08:59
  • 1
    See this answer for generic void unique_ptr: https://stackoverflow.com/a/39288979/2527795 – VLL Jan 16 '20 at 09:01
  • Please note that there should almost never be a reason to use `malloc` in C++ like this. You are returning a pointer to raw memory, that you need to placement-new objects into before you are allowed to use it. If you don't have a good reason to create the objects at a later time than when you are allocating memory, then you should use `new` or `std::make_unique` which will allocate memory, as well as create appropriate objects. In either case `std::vector` with `reserve` is prob. better too. Even if you don't use these, `operator new` is the idiomatic way of allocating memory, not `malloc`. – walnut Jan 16 '20 at 19:19

3 Answers3

19

You need to specify custom deleter in order to use void as unique_ptr's type argument like that:

#include <memory>
#include <cstdlib>

struct deleter {
    void operator()(void *data) const noexcept {
        std::free(data);
    }
};

std::unique_ptr<void, deleter> get_ptr(std::size_t size) {
    return std::unique_ptr<void, deleter>(std::malloc(size));
}

#include <cstdio>
int main() {
    const auto p = get_ptr(1024);
    std::printf("%p\n", p.get());
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
2

A simplification of @RealFresh's answer using std::free directly as deleter instead of constructing a functor:

auto get_ptr(std::size_t size) {
    return std::unique_ptr<void, decltype(&std::free)>(std::malloc(size), std::free);
}

See my comment on the question, though.

walnut
  • 21,629
  • 4
  • 23
  • 59
1

Consider returning a pointer to char-array instead:

#include <memory>

std::unique_ptr<char[]> get_ptr(std::size_t size)
{
    return std::make_unique<char[]>(size);
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103