Imo's correct answer is neither one nor the other. Usually there is no need to return the original pointers from functions in your own code (exceptions below).
Instead, simply return the created object:
class B { virtual ~B(){} }; class D : public B {};
This is enough anyway. Moreover, and, importantly, it expresses what you get, namely an object of type D , which you can use as needed. Instead, when you get a raw pointer, it is from the first (i.e., not realizing the behavior on behalf of a function, reading documentation, etc.), It is not clear what you are allowed to do with this raw pointer. Can you wrap it inside unique_ptr ? Can you delete it? Unclear. Returning an object (or, better, a well-designed object, which basically means serial RAII) frees you from having to answer this question - just do what you want with the object.
Also, if you really need a pointer (which is an abstraction from an object), you can still put the return inside a suitable smart pointer, for example
auto d_uptr = std::make_unique<D>(createDerived()); auto d_sptr = std::make_shared<D>(createDerived());
or, likewise, also in smart base class pointers,
std::unique_ptr<B> = std::make_unique<D>(createDerived()); std::shared_ptr<B> b_sptr = std::make_shared<D>(createDerived());
In this case, a copy of elision is used to construct the pointers and does not create overhead compared to your function returning D* . Please note that, as a rule, a pointer should be a smart pointer, because only then will you be released directly from the obligation to correctly delete it somewhere later in the code.
The only exception where you need source pointers as return function types is the cloning pattern, which is used when you want to copy an object using a base class pointer. Here you need to use smart pointers, as well as a function called by the user, but you need to use raw pointers inside the class to allow covariant types of returned virtual functions:
class B { virtual ~B(){} auto clone() const { return std::unique_ptr<B>(clone_impl()); } protected: virtual B* clone_impl() const = 0; }; class D : public B { protected: virtual D* clone_impl() const { return new D{*this}; }; };
There can be many other exceptions (for example, always when covariance is used) that I donβt remember at the moment. But they are not so important.
To summarize: don't use source pointers as return functions unless you have a good reason for this.