make_shared
allocates the object in the same block of memory as the control block. This improves cache coherency and cuts out an allocation.
One way to permit make_shared
to do this is to have a private token within your class, and a public constructor that consumes that token.
class Object {
private:
struct token_t{ private: token_t() {}; friend class Object; };
static token_t token() { return {}; }
Object() = default;
public:
Object( token_t ):Object() {}
};
now we can make_shared<Object>( Object::token() )
.
This gives us one allocation, and doesn't violate the privacy of the construction as only things with access to private fields of Object
can call that constructor. They can, however, pass the token to another function (like make_shared
) and it in turn can call the constructor in question. This works with more arguments, naturally.
As for your syntax:
std::shared_ptr<Object> myObject = (std::shared_ptr<Object>) new Object();
(std::shared_ptr<Object>) new Object();
simply explicitly constructs a shared_ptr<Object>
from new Object()
. It is equivalent to std::shared_ptr<Object>(new Object)
.
We then take this prvalue and construct myObject
from it. In C++03 11 and 14, this copy/move construction is elided. In C++17, the prvalue "construction instructions" are directly applied to myObject
. In practice, this results in the same machine code (unless you are a fool and explicitly tell your compiler to not elide construction).
In short, it works. The only downside is the double-allocation of the separate control-block from the Object
allocation.