std::make_shared
和 new
都用于动态分配内存并返回指向该内存的指针,但它们之间有一些重要的区别。下面详细解释它们之间的差异:
-
内存分配方式:
std::make_shared
:该函数是一个模板函数,会在内存中分配一块足够大的内存来存储对象及其控制块(用于跟踪引用计数等信息),然后在此内存上构造对象。因此,std::make_shared
一次性完成了内存分配和对象构造。new
:使用new
运算符动态分配内存时,会首先分配足够的内存来存储对象,并返回指向该内存的指针。然后,必须显式地调用构造函数来在该内存上构造对象。
-
性能:
std::make_shared
通常比直接使用new
更高效,因为它只需一次内存分配和一次构造函数调用。而使用new
则需要两次内存分配(对象内存和控制块内存)和一次构造函数调用。- 另外,
std::make_shared
还可以减少内存碎片化,因为它在一次分配中为对象和控制块分配了连续的内存。
-
异常安全性:
std::make_shared
在内存分配和对象构造过程中提供了强异常安全性。如果在分配内存或构造对象时抛出异常,std::make_shared
会自动处理已分配的内存,确保没有内存泄漏,并且不会部分构造对象。- 使用
new
时,如果在分配内存后抛出异常,可能会导致内存泄漏,因为在异常抛出前分配的内存无法释放。
-
代码简洁性:
std::make_shared
可以使代码更加简洁,因为它结合了内存分配和对象构造,并且不需要指定对象的类型(由模板参数推导)。- 使用
new
时,需要显式地指定对象类型,并且需要两步操作:分配内存和构造对象。
综上所述,优先使用 std::make_shared
来动态分配对象,因为它在性能、异常安全性和代码简洁性方面都有优势。只有在特定情况下(例如需要控制对象和控制块的内存分配)才考虑使用 new
。