When you use std::make_shared, the control and the data block of the std::shared_ptr will be allocated together using a single allocation. Since, the control block needs to stay alive as long as there are std::shared_ptrs and std::weak_ptrs to the same data, the data block must stay alive as well and can thus not be destructed straight away. When you use new instead, the control and the data block will be allocated separately. This implies that the data block can be destructed when there are no std::shared_ptrs to the same data (independent of the existence of std::weak_ptrs to the same data). (Cfr. https://stackoverflow.com/a/18301738/1731200)
So far the theory ;P . I tried to see this in practice using a small code sample. But somehow the data block is always destructed before resetting the std::weak_ptrs to the same data for both GCC and Clang. Is this behavior just compiler implementation dependent?
#include <memory>
#include <iostream>
struct Widget {
~Widget() {
std::cout << "Widget::~Widget()" << std::endl;
}
int data;
};
void test(bool use_make_shared) {
std::shared_ptr< Widget > sp;
if (use_make_shared) {
sp = std::make_shared< Widget >();
} else {
sp = std::shared_ptr< Widget >(new Widget());
}
std::weak_ptr< Widget > wp(sp);
sp.reset();
std::cout << "No std::shared_ptr's anymore." << std::endl;
wp.reset();
std::cout << "No std::weak_ptr's anymore." << std::endl;
}
int main() {
test(true);
std::cout << std::endl;
test(false);
};
Widget::~Widget()
No std::shared_ptr's anymore.
No std::weak_ptr's anymore.
Widget::~Widget()
No std::shared_ptr's anymore.
No std::weak_ptr's anymore.