stakx stakx - 4 months ago 9
C++ Question

Destruction policy for `std::unique_ptr<Base>(ptr)` when I don't know how `ptr` was allocated?

Another "modern C++" beginner question. I seem to have some misconception about how to properly use smart pointers / smart pointer destruction policies.

struct Base {
virtual Base* clone() const = 0;
virtual ~Base() { }
};

void clone_and_use(const Base &original) {
auto clone = std::unique_ptr<Base>(original.clone());
… // do something with `clone`
}


As far as I can tell, when
clone
goes out of scope, the pointed-to memory will be
delete
d thanks to the
std::default_delete<Base>
destruction policy used by
std::unique_ptr<Base>
(which appears to be equivalent to
std::unique_ptr<Base, std::default_delete<Base>>
).

What if
original.clone()
returned a pointer to memory that was not allocated with
new
? Obviously the standard
std::default_delete<Base>
destruction policy would be inappropriate—
delete
should only be used together with
new
, but not with
new[]
,
malloc
, or anything else— and I should specify a different destruction policy when I create the
clone
smart pointer… but which one would I specify?

auto clone = std::unique_ptr<Base, ?>(original.clone());
// ^


I am guessing that I would have to extend
Base
such that I can simply ask any derived type to provide a destruction policy suitable for its
clone()
implementation, but I'm not exactly sure how I would do this.

Can someone show me how to:


  • Define the
    Base
    interface such that it can support a
    clone()
    method without leading to leaked or incorrectly freed memory; and

  • How to properly work with smart pointer destruction policies (if they are necessary at all in this example)?


Nim Nim
Answer

Your clone() should return a smart pointer appropriately, i.e.

virtual std::unique_ptr<Base> clone() {
...
}

This avoids all ambiguity.