I am working with a code base which makes extensive use of the following syntax:
shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();
I noticed that I cannot access private constructors with make_shared
, but shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();
works just fine. Should I be using it just because it seems to work? Are there any dangers? How is it different than make_shared
?
I am aware of the answer in this question, which makes comparisons between make_shared
and:
std::shared_ptr<Object> p2(new Object("foo"));
but I haven't been able to find a reference to the syntax I came across. Is it different, or is it the same as the above?
So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object. When to use shared_ptr? Use shared_ptr if you want to share ownership of a resource.
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr . Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.
The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.
shared_ptr is now part of the C++11 Standard, as std::shared_ptr . Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically allocated array. This is accomplished by using an array type ( T[] or T[N] ) as the template parameter.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With