C++ make_shared
C++ make_shared 是 C++11 引入的一个标准库函数模板,用于高效地创建和管理 shared_ptr 对象。它是现代 C++ 内存管理的重要工具,能够减少动态内存分配的开销并提高代码安全性。
概述[编辑 | 编辑源代码]
std::make_shared
是一个工厂函数,用于构造一个对象并返回指向它的 std::shared_ptr
。与直接使用 std::shared_ptr
构造函数相比,它具有以下优势:
- **性能优化**:通常只需一次内存分配(对象和控制块合并分配)。
- **异常安全**:避免因构造参数求值顺序导致的潜在内存泄漏。
- **代码简洁性**:减少显式
new
的使用。
其函数原型如下:
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
基本用法[编辑 | 编辑源代码]
以下示例展示如何用 make_shared
创建一个 shared_ptr
:
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass(int value) : data(value) {
std::cout << "MyClass constructed with value: " << data << std::endl;
}
~MyClass() {
std::cout << "MyClass destroyed with value: " << data << std::endl;
}
void print() const { std::cout << "Value: " << data << std::endl; }
private:
int data;
};
int main() {
auto ptr = std::make_shared<MyClass>(42); // 创建 shared_ptr
ptr->print();
return 0;
}
输出:
MyClass constructed with value: 42 Value: 42 MyClass destroyed with value: 42
与传统方法的对比[编辑 | 编辑源代码]
传统方式使用 shared_ptr
构造函数:
std::shared_ptr<MyClass> ptr(new MyClass(42)); // 需要两次内存分配
而 make_shared
通常合并对象和控制块的内存分配,效率更高。
内存分配机制[编辑 | 编辑源代码]
数学上,若对象大小为 ,控制块大小为 ,则:
- 传统方式:总分配量 = (可能不连续)
make_shared
:总分配量 ≤ (连续内存)
实际应用场景[编辑 | 编辑源代码]
容器存储[编辑 | 编辑源代码]
在容器中管理动态对象时,make_shared
可简化代码并提高性能:
std::vector<std::shared_ptr<MyClass>> vec;
vec.push_back(std::make_shared<MyClass>(10));
vec.push_back(std::make_shared<MyClass>(20));
工厂模式[编辑 | 编辑源代码]
工厂函数返回 shared_ptr
时推荐使用:
class Factory {
public:
static std::shared_ptr<MyClass> create(int val) {
return std::make_shared<MyClass>(val);
}
};
注意事项[编辑 | 编辑源代码]
1. **自定义删除器**:make_shared
不支持自定义删除器,需直接使用 shared_ptr
构造函数。
2. **大对象延迟释放**:合并分配可能导致对象内存直到所有 weak_ptr
释放后才被回收。
3. **构造函数私有**:若类构造函数私有,需声明 make_shared
为友元。
高级主题[编辑 | 编辑源代码]
异常安全保证[编辑 | 编辑源代码]
以下代码可能因异常导致内存泄漏:
foo(std::shared_ptr<MyClass>(new MyClass(42)), bar()); // 若 bar() 抛出异常
改用 make_shared
可避免:
foo(std::make_shared<MyClass>(42), bar()); // 安全
[编辑 | 编辑源代码]
std::allocate_shared
允许自定义分配器,适用于特殊内存池场景。
总结[编辑 | 编辑源代码]
std::make_shared
是现代 C++ 中创建 shared_ptr
的首选方法,兼顾性能与安全性。初学者应优先掌握其基本用法,高级用户可进一步探索其内存模型和异常安全特性。