贡献者: addis; admin
// 创建(无法指定删除器,默认用 delete 释放)
auto ptr = make_unique<int>(42); // 等效于 unique_ptr<int> ptr(new int(42));
unique_ptr<int> ptr2 = std::move(ptr1); // 转移所有权
int* rawPtr = ptr.release(); // 释放所有权并返回裸指针(被管理的对象不会被释放)
int* rawPtr = ptr.get(); // 返回裸指针(不释放所有权)
ptr.reset(); // 手动释放对象
ptr.reset(ptr3); // 释放当前对象并管理新的对象
// 自定义删除器类
struct Deleter {
void operator()(int* ptr) {
cout << "Deleting resource: " << *ptr << endl;
delete ptr;
}
};
// 用法
unique_ptr<int, Deleter> ptr(new int(42)); // 默认使用 Deleter() 新建删除器
unique_ptr<int, Deleter> ptr2(new int(42), Deleter()); // 手动提供删除器
unique_ptr<类> p(类 *类指针),其中 类指针 可以由 new 类(构造参数...) 产生,指向一个需要 delete 类指针 的对象。
unique_ptr<类[]> p(类 *类指针),其中 类指针 可以由 new 类[数量] 产生,指向一个需要 delete[] 类指针 的对象。
unique_ptr<int[]> p(new int[10]) 不能写成 unique_ptr<int[]> p = new int[10] 会导致编译错误因为类型不对。
auto ptr = std::make_unique<MyClass>(arg1, arg2, ...); 等效于 auto ptr = std::unique_ptr<MyClass>(new MyClass(arg1, arg2, ...));。
auto arr_ptr = std::make_unique<MyClass[]>(5); 可以创建长度为 5 的 int 数组。
std::make_unique<int[10]>() 这种用法是不支持的。
p 的引用或指针。允许 std::move()。
unique_ptr<类,删除器类> p(类指针, 删除器)。删除器 是 删除器类 的一个对象(例如 C 函数指针)。
删除器类 或 删除器 可以省略,省略后默认用对应的 delete 类指针 或 delete[] 类数组,实际上是 std::default_delete<T>(对数组进行了特化)。
删除器 需要可以像 void 函数名(类 *p) 一样使用。它几乎可以是任何 callable(例如具有 operator() 的对象)
unique_ptr 的 destructor 会调用 删除器(类指针) 释放内存。
*, ->, [],也可以对 unique_ptr 使用。
p.get() 返回 类指针。p.get_deleter() 返回 删除器 的 ref。
p.reset(新指针) 调用原来对象的删除器,并管理新的对象。p.reset() 释放对象。
if(p) 或 bool(p) 可以判 p 是否在管理一个对象。例如默认构造函数产生 p。或者 p.reset() 后的就会是 false。
unique_ptr,那么将造成重复 delete 错误,行为未定义,这也是为什么要尽量用 make_unique
shared_ptr 都释放所有权,管理的对象才会被删除器释放。
p.use_count() 返回有几个 shared_ptr 正在使用。
p.reset() 和 p.reset(p3) 用法同 unique_ptr
std::shared_ptr<int> ptr(new int(42), custom_deleter);
shared_ptr<void> 可以装任何指针
shared_ptr 管理的对象会有一个 control block 即控制块,它所有的 shared_ptr 都会有个指针指向这个 block。里面记录了该对象的 deleter, allocator, 分别有几个 shared_ptr 和 weak_ptr(也就是 shared_count 和 weak_count)
MyClass* raw = ptr.get(); 可以返回裸指针,但不可以手动把它释放或使用它创建新的 shared_ptr。
shared_ptr。p2 = p 即可,copy constructor 也行。
auto p = make_shared<int>();
auto p_arr = make_shared<int[]>(10); 需要 C++17
shared_ptr,或者 weak_ptr 初始化
p.lock() 创建出管理对象的一个新的 shared_ptr
p.expired() 可以检查对象是否已经被删除。
#include <iostream>
#include <memory>
class Node {
public:
shared_ptr<Node> next;
weak_ptr<Node> prev; // weak_ptr to avoid circular reference
~Node() {
cout << "Node destroyed" << endl;
}
};
int main() {
shared_ptr<Node> node1 = make_shared<Node>();
shared_ptr<Node> node2 = make_shared<Node>();
node1->next = node2;
// This would create a circular reference if prev were a shared_ptr
node2->prev = node1;
cout << "node1 use count: " << node1.use_count() << endl; // 1
cout << "node2 use count: " << node2.use_count() << endl; // 2
return 0;
}
shared_count 和 weak_count 中,前者控制被管理的对象是否销毁。后者控制控制块是否被销毁。
shared_count 和 weak_count 都是线程安全的,可以在多个线程中任意改变。
weak_ptr 不提供 get() 成员,无法直接返回裸指针。因为这是线程不安全的,因为有可能 get() 调用以后、裸指针使用以前,其他线程会把对象销毁。所以必须要先用 lock() 返回一个 shared_ptr,把这个对象锁住,再用 shared_ptr 返回裸指针才能安全使用。这也是 lock() 名字的由来:把对象锁住不让它释放。
 
 
 
 
 
 
 
 
 
 
 
友情链接: 超理论坛 | ©小时科技 保留一切权利