class MyClass
{
public:
MyClass();
~MyClass();
private:
};
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
void test_08()
{
std::shared_ptr<MyClass> myclass_shared_ptr = std::make_shared<MyClass>();
std::shared_ptr<MyClass> myclass_make_shared(new MyClass);
}
区别就是std::shared_ptr构造函数会执行两次内存申请,而std::make_shared只执行一次,由于shared_ptr在实现的时候使用的refcount技术,因此内部会有一个计数器(控制块,用来管理数据)和一个指针,指向数据,因此在执行的时候首先会申请数据的内存,然后申请控制块,因此是两次内存申请,而make_shared则是执行一次内存申请,将数据与控制块的申请放到一起。
异常安全:
考虑下面一段代码:
void f(std::shared_ptr<Lhs> &lhs, std::shared_ptr<Rhs> &rhs){...}
f(std::shared_ptr<Lhs>(new Lhs()),
std::shared_ptr<Rhs>(new Rhs())
);
因为C++允许参数在计算的时候打乱顺序,因此一个可能的顺序如下:
new Lhs()
new Rhs()
std::shared_ptr
std::shared_ptr
此时假设第2步出现异常,则在第一步申请的内存将没处释放了,上面产生内存泄露的本质是当申请数据指针后,没有马上传给std::shared_ptr,因此一个可能的解决办法是:
auto lhs = std::shared_ptr<Lhs>(new Lhs());
auto rhs = std::shared_ptr<Rhs>(new Rhs());
f(lhs, rhs);
而一个比较好的方法是使用 std::make_shared 。
f(std::make_shared<Lhs>(),
std::make_shared<Rhs>()
);
make_shared的缺点
因为make_shared只申请一次内存,因此控制块和数据块在一起,只有当控制块中不再使用时,内存才会释放。