I was experimenting with shared_ptr
and make_shared
from C++11 and programmed a little toy example to see what is actually happening when calling make_shared
. As infrastructure I was using llvm/clang 3.0 along with the llvm std c++ library within XCode4.
class Object
{
public:
Object(const string& str)
{
cout << "Constructor " << str << endl;
}
Object()
{
cout << "Default constructor" << endl;
}
~Object()
{
cout << "Destructor" << endl;
}
Object(const Object& rhs)
{
cout << "Copy constructor..." << endl;
}
};
void make_shared_example()
{
cout << "Create smart_ptr using make_shared..." << endl;
auto ptr_res1 = make_shared<Object>("make_shared");
cout << "Create smart_ptr using make_shared: done." << endl;
cout << "Create smart_ptr using new..." << endl;
shared_ptr<Object> ptr_res2(new Object("new"));
cout << "Create smart_ptr using new: done." << endl;
}
Now have a look at the output, please:
Create smart_ptr using make_shared...
Constructor make_shared
Copy constructor...
Copy constructor...
Destructor
Destructor
Create smart_ptr using make_shared: done.
Create smart_ptr using new...
Constructor new
Create smart_ptr using new: done.
Destructor
Destructor
It appears that make_shared
is calling the copy constructor two times. If I allocate memory for an Object
using a regular new
this does not happen, only one Object
is constructed.
What I am wondering about is the following. I heard that make_shared
is supposed to be more efficient than using new
(1, 2). One reason is because make_shared
allocates the reference count together with the object to be managed in the same block of memory. OK, I got the point. This is of course more efficient than two separate allocation operations.
On the contrary I don't understand why this has to come with the cost of two calls to the copy constructor of Object
. Because of this I am not convinced that make_shared
is more efficient than allocation using new
in every case. Am I wrong here? Well OK, One could implement a move constructor for Object
but still I am not sure whether this this is more efficient than just allocating Object
through new
. At least not in every case. It would be true if copying Object
is less expensive than allocating memory for a reference counter. But the shared_ptr
-internal reference counter could be implemented using a couple of primitive data types, right?
Can you help and explain why make_shared
is the way to go in terms of efficiency, despite the outlined copy overhead?