std::unique_ptr管理动态分配内存的方式
- 所有权唯一:
std::unique_ptr
拥有对动态分配对象的唯一所有权。一旦 std::unique_ptr
被销毁,它所管理的对象也会被自动销毁。
- 实现机制:
std::unique_ptr
通常以一个裸指针作为其内部成员变量来指向动态分配的对象。例如,std::unique_ptr<int> ptr(new int(5));
,这里 ptr
内部持有一个指向 new int(5)
所分配内存的指针。
- 移动语义:
std::unique_ptr
支持移动语义,不支持拷贝语义。这意味着可以通过 std::move
将 std::unique_ptr
的所有权转移给另一个 std::unique_ptr
。例如:
std::unique_ptr<int> ptr1(new int(5));
std::unique_ptr<int> ptr2 = std::move(ptr1);
// 此时ptr1不再拥有对象,ptr2拥有
- 自动释放内存:当
std::unique_ptr
对象超出其作用域(例如函数结束),其析构函数会被调用,进而释放其所管理的动态分配内存。例如:
void func() {
std::unique_ptr<int> ptr(new int(10));
// 函数结束,ptr析构,释放内存
}
与std::shared_ptr在内存管理上的不同
- 所有权模型:
std::unique_ptr
是独占所有权,同一时间只有一个 std::unique_ptr
可以指向一个对象。
std::shared_ptr
是共享所有权,多个 std::shared_ptr
可以指向同一个对象,通过引用计数来管理对象的生命周期。当引用计数为0时,对象被销毁。
- 内存开销:
std::unique_ptr
通常只需要一个指针的大小,因为它只需要存储指向对象的指针。
std::shared_ptr
除了存储指向对象的指针外,还需要额外的空间来存储引用计数等控制块信息,因此内存开销相对较大。
- 性能:
std::unique_ptr
由于所有权唯一,操作简单,性能开销小,特别是在转移所有权时(移动语义),只需要简单地转移内部指针。
std::shared_ptr
在引用计数的增加、减少操作上有一定的性能开销,尤其是在多线程环境下,需要使用原子操作来保证引用计数的线程安全,进一步增加了开销。
- 应用场景:
std::unique_ptr
适用于一个对象只应由一个所有者管理的场景,如函数内部局部对象管理,避免对象被意外拷贝。
std::shared_ptr
适用于需要多个对象共享同一资源的场景,如多个模块需要访问同一个数据结构,并且该数据结构的生命周期由最后一个使用者决定。