为什么 unique_ptr 需要明确知道类型的析构函数这个问题是我写 unique_ptr 调试接口的时候才注意到的,之前确实不知道。为什么会这样呢?...假设内部是这么实现的 (一般会运用空基类优化把 Deleter 的空间优化掉,libstdc++ 里把他们放进了一个 tuple。...默认构造的时候允许是不完整类型。为什么会这样呢?shared_ptr 怎么处理 Deleter 呢?...(还记得吧, Deleter 就是智能指针析构时候的删除操作)在常见编译器的实现里,shared_ptr 把 Deleter(包括默认情况下的 operator delete)放进一个叫做 control...Deleter 的类型在 control block 的具体类型上,shared_ptr 本身只持有一个 control block 基类的指针,通过虚函数来调用 Deleter。
如果有自定义 deleter,还需要保存 deleter 的信息。 shared_ptr 需要维护的信息有两部分: 指向共享资源的指针。...shared_ptr 的 的 deleter 是保存在控制信息中,所以,是否有自定义 deleter 不影响 shared_ptr 对象的大小。...image 复制一个 shared_ptr : std::shared_ptr sptr2 = sptr1; ?...image 为什么控制信息和每个 shared_ptr 对象都需要保存指向共享资源的指针?可不可以去掉 shared_ptr 对象中指向共享资源的指针,以节省内存开销? 答案是:不能。...image enable_shared_from_this 一个类的成员函数如何获得指向自身(this)的 shared_ptr? 看看下面这个例子有没有问题?
在博文https://blog.csdn.net/qq_27717921/article/details/82940519已经介绍了unique_ptr和shared_ptr的使用,但是这两类的智能指针是如何做到管理指针的呢...采用new返回的指针初始化shared_ptr,调用构造函数,在堆上开辟一块存储空间,存放指向这块空间指针的数量,这块空间的地址初始化use_c. new int(2)返回的指针用于初始化p. 2. shared_ptr..., rhs.deleter); } 函数swap操作,主要是交换shared_ptr的成员变量,比如p.use_c = 0xff11ff12, p.p = 0x12fa2334, p.deleter=0xd232455f...2, 这个地方拷贝构造弯沉后已经完全相同了,为什么还有调用swap操作, 为了递减赋值号左侧对象的use_c, 这个时候rhs存放的就是赋值号左侧的信息,在=结束后临时变量会调用析构函数, 从而减少左侧的...release函数 ~UniquePointer() { deleter(p); } 和shared_ptr的析构函数不同,unique_ptr的析构函数更简单, 只需要调用类型T的析构函数,如果是自定义类型需要重写
智能指针主要思想是RAII思想,“使用对象管理资源”,在类的构造函数中获取资源,在类的析构函数中释放资源。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。 ...RAII是Resource Acquisition Is Initialization的简称,即资源获取就是初始化: 1.定义一个类来封装资源的分配与释放; 2.构造函数中完成资源的分配及初始化...,是一个轻量级的智能指针,适合用来管理生命周期比较短或者不会被远距离传递的动态对象,最好是局限于某个函数内部或者是某个类的内部。... (3) 管理数组指针时,需要制定Deleter以使用delete[]操作符销毁内存,shared_ptr并没有针对数组的特化版本; (4) 不能把一个原生指针交给两个智能指针对象管理,对其它智能指针也是如此...m_pT; } 三、总结 智能指针就是模拟指针动作的类,一般智能指针都会重载 -> 和 * 操作符。
一、技术背景与设计初衷 1 unique_ptr • 目标:独占资源,不可复制,只能移动(move) • 使用场景:资源唯一所有权,RAII 风格自动释放 • 核心问题: • 避免内存泄漏 • 支持移动语义...1 shared_ptr • 目标:多方共享资源,引用计数控制生命周期 • 使用场景:多线程共享对象、缓存管理 • 核心问题: • 自动管理生命周期 • 处理多线程环境下的引用计数(atomic) •.../ 原始指针 Deleter deleter; // 删除器 public: explicit unique_ptr(T* p = nullptr) noexcept : ptr(p)...1 unique_ptr • Ceph 的对象缓存(ObjectCacher)中,每个缓存条目独占内存块 • TiDB Executor 局部临时对象管理 1 shared_ptr • Ceph 多线程...unique_ptr,必须共享就用 shared_ptr,控制引用计数就是控制你的性能。”
转自: https://www.boost.org/doc/libs/1_74_0/libs/smart_ptr/doc/html/smart_ptr.html#techniques boost写的智能指针技术...; } }; public: static shared_ptr create() { shared_ptr px(new X, X::deleter...pointer, using get_deleter: void extract_another_from_shared(shared_ptr px) { typedef smart_pointer_deleter... > deleter; if(deleter const * pd = get_deleterdeleter>(px)) { another_ptr...a shared_ptr to itself, using a null_deleter: class X { private: shared_ptr this_; int i
多个 shared_ptr 实例可以同时管理同一个对象,当最后一个持有该对象的 shared_ptr 被销毁时,对象才会被自动释放。...、shared_ptr 原理2.1 引用计数机制shared_ptr 的核心是引用计数(reference count):每个被管理的对象都有一个关联的引用计数器,记录当前有多少个 shared_ptr...std::atomic 确保引用计数的线程安全增加计数使用 memory_order_relaxed(仅需原子性)减少计数使用 memory_order_acq_rel(确保资源释放的正确顺序)控制块的多态设计基类...ControlBlockBase 定义通用接口派生类 ControlBlock 处理具体类型和删除器支持不同类型的删除器和分配器拷贝与移动语义拷贝操作增加引用计数移动操作转移所有权,不修改引用计数析构时减少计数...线程安全注意事项shared_ptr 本身的引用计数操作是线程安全的但管理的对象不是线程安全的,仍需同步机制保护六、shared_ptr 与 unique_ptr 对比特性shared_ptrunique_ptr
①unique_ptr 在C++中,unique_ptr是一个智能指针(smart pointer)类模板,用于管理动态分配的内存资源,它提供了自动释放内存的功能。...不可拷贝:unique_ptr是不可拷贝的,即不能进行复制构造和赋值操作。这是为了确保独占所有权的特性,防止多个指针同时管理同一个对象的内存。...②shared_ptr 在C++中,shared_ptr是一个智能指针(smart pointer)类模板,用于管理动态分配的内存资源。...指针语义:shared_ptr的使用方式与原始指针相似,可以通过指针操作符(->)和解引用操作符(*)来访问所指向对象的成员。 可拷贝:shared_ptr是可拷贝的,即可以进行复制构造和赋值操作。.../ 复制构造函数,共享同一块内存 std::shared_ptr ptr2 = ptr1; // 增加引用计数 std::cout << ptr1.use_count
将这个智能指针定义为一个模版main函数结束之后会自动进行析构操作的 释放对象资源是借助类的析构函数auto_ptr会让被拷贝对象被架空unique_ptrunique_ptr 是 C++ 标准库中的智能指针...引用计数原理shared_ptr 内部维护一个引用计数器,记录有多少个 shared_ptr 共享同一个对象。每次复制(如拷贝构造、赋值)时计数加 1,每次释放(如析构、重置)时计数减 1。...); };std::shared_ptr file(fopen("test.txt", "r"), file_deleter);5....namespace bit{ // 智能指针类模板,实现引用计数的共享所有权 // 模板参数T为指针指向的对象类型 template class shared_ptr...好的!下面是你提供的 shared_ptr 智能指针类模板的逐行详细中文解释,覆盖了构造、析构、拷贝、赋值、资源管理等各个方面。此实现模拟了标准库中的 std::shared_ptr 的核心思想。
一、为什么需要使用智能指针 (一)内存泄漏 C++在堆上申请内存后,需要手动对内存进行释放。代码的初创者可能会注意内存的释放,但随着代码协作者加入,或者随着代码日趋复杂,很难保证内存都被正确释放。...但由于unique_ptr不能进行复制,因此部分场景下不能使用的。 unique_ptr的使用场景 unique_ptr一般在不需要多个指向同一个对象的指针时使用。...:forwarddeleter_type>(__u.get_deleter())) { } // 移动赋值函数,取出原有unique_ptr的指针和析构器进行构造 unique_ptr& operator...会将shared_ptr的成员变量地址进行复制。...浅谈Golang两种线程安全的map 公司的电脑为什么卡——因为缺少工程师文化!
一、为什么需要使用智能指针 1.1 内存泄漏 C++在堆上申请内存后,需要手动对内存进行释放。代码的初创者可能会注意内存的释放,但随着代码协作者加入,或者随着代码日趋复杂,很难保证内存都被正确释放。...但由于unique_ptr不能进行复制,因此部分场景下不能使用的。 3.1.1 unique_ptr 的使用场景 unique_ptr一般在不需要多个指向同一个对象的指针时使用。..., _VSTD::forwarddeleter_type>(__u.get_deleter())) { } // 移动赋值函数,取出原有unique_ptr的指针和析构器进行构造 unique_ptr..._shared_weak_owners_(__refs) {} protected: virtual ~__shared_weak_count(); public: // 调用通过父类的...会将shared_ptr的成员变量地址进行复制。
一、裸指针的 “血泪史”:为什么我们需要智能指针? 在深入智能指针之前,我们先回顾一下裸指针(Raw Pointer)的 “坑”。正是这些痛点,催生了智能指针的诞生。...简单来说,智能指针是一个 “包装器类”,它封装了裸指针,并在其析构函数中自动执行delete操作。...2.1.1 unique_ptr 的核心原理 unique_ptr的底层实现非常简洁: 封装一个裸指针(T* ptr); 禁用拷贝构造函数和拷贝赋值运算符(C++11 中通过= delete实现),确保所有权无法被复制...:观察者模式 class Subject; // 前向声明 // 观察者类(弱引用主题,避免循环引用) class Observer { public: Observer(const shared_ptr...array 3.1.2 shared_ptr 的定制删除器 shared_ptr的定制删除器是构造函数的参数,语法更灵活 void test_custom_deleter_shared() {
Sometimes you won't remember. std::shared_ptr shared_ptr 是一个 pointer wrapper,其实就是个模板类。...最后其析构函数负责"释放"其内存,即默认的 Deleter 调用 operator delete()....复制构造也是保证不会 throw 的。...为什么推荐使用 make_shared 而不推荐 shared_ptr x(new T(args...))?...即类A有 shared_ptr member,而类B有 shared_ptr member。 解决方法: 应当至少使用一个 weak_ptr,具体情况具体分析。
不能复制,但可以通过 std::move 转移所有权。...2.5 定制删除器 在 C++ 中,自定义删除器(Custom Deleter)用于指定智能指针在销毁资源时所使用的自定义清理操作。...使用 lambda 表达式作为自定义删除器 auto deleter = [](int* p) { std::cout shared_ptr managed...\n"; delete p; }; std::shared_ptr ptr(new int(42), deleter); std::cout 的动态内存 静态指针分配的动态内存未释放 对象泄漏 动态创建对象未销毁 类的析构函数未正确释放资源 资源泄漏 文件、网络等系统资源未释放 文件未关闭,数据库连接未释放
=&other){reset();//释放当前管理的资源ptr=other.ptr;deleter=std::move(other.deleter);other.ptr=nullptr;//关键:置空源指针...二、std::shared_ptr:共享所有权的协作std::shared_ptr实现了“共享所有权”(SharedOwnership)。多个shared_ptr实例可以安全地共享同一个对象。...1.核心机制:控制块(ControlBlock)shared_ptr的真正智慧在于其控制块。它是一个动态分配的内存块,包含管理资源所需的所有元数据。...;控制块和管理的对象在内存中的关系如下图所示:收起代码语言:TXTAI代码解释graphLRsubgraph"Stack(线程安全)"SP1[shared_ptr]SP2[shared_ptr]WP[weak_ptr...{returnnullptr;//对象已被销毁,返回空}}三、性能开销:共享并非无代价std::shared_ptr的强大功能带来了不可避免的开销:内存开销:每个shared_ptr实例本身的大小大约是裸指针的两倍
按是否要求资源对象自己维护引用计数,C++引用计数方案可以分为两类: 侵入式:侵入式的引用计数管理要求资源对象本身维护引用计数,同时提供增减引用计数的管理接口。...,可以自定义一个什么也不做的deleter: struct noop_deleter { void operator()(void*) { // NO-OP...(话说回来,这倒并不是说noop_deleter这种手法毫无用处,Boost.Asio中就巧妙地利用shared_ptr、weak_ptr和noop_deleter来实现异步I/O事件的取消)。...通常,使用shared_ptr的资源对象必须动态分配,最常见的就是直接从堆上new出一个实例并交付给一个shared_ptr,或者也可以从某个资源池中分配再借助自定义的deleter在引用计数归零时将资源放回池中...为了解决这个问题,Boost提供了一个类模板enable_shared_from_this: 所有需要在成员方法中获取指向this的shared_ptr的类型,都必须以CRTP手法继承自enable_shared_from_this
纯虚函数和抽象类 纯虚函数: 一个类中可以包含纯虚函数,通过在函数声明的末尾添加 = 0 来声明纯虚函数。含有纯虚函数的类是抽象类,无法实例化,只能用作基类。...派生类必须实现(覆盖)抽象类中的纯虚函数,否则它们也会成为抽象类。 4. 有了解C++的shared_ptr 吗?...当最后一个指针被销毁时,它会自动释放所管理的对象。 自定义删除器(Deleter): 可以提供一个自定义的删除器函数(deleter function)来处理特定的资源释放操作。...auto deleter = [](int* p) { // 自定义释放资源的操作 delete p; }; std::shared_ptr customPtr(new int...(20), deleter); 使用注意事项 避免循环引用:std::shared_ptr 可能会出现循环引用导致资源无法释放的问题。
一、产生的原因 shared_ptr的产生与unique_ptr类似,都是为了解决raw pointer的new和delete的成对使用,导致的野指针、内存泄漏、重复释放内存等。...特性2: 共享,使用shared_ptr的指针可以共享同一块内存中的数据。...cout deleter\n"; std::shared_ptr sh4(new Foo, D());...with object and deleter Foo......__cntrl_->__release_shared(); } 涉及到的引用计数类的声明 class __shared_count { // 引用计数的操作类 // not
1.3 为什么需要自定义删除器 1.2.1 管理非堆内存资源 除了内存,智能指针还可以用于管理其他类型的资源,例如文件句柄、互斥锁或数据库连接。这些资源可能需要特定的释放机制。...2.1.1 什么是函数对象 函数对象是重载了operator()的类或结构体。这意味着你可以像调用函数一样使用这些对象。...std::unique_ptrdeleter)> p(new int, deleter); 这种方式的优点是简洁和直观。...你不需要定义一个完整的结构体或类,只需要一个简单的Lambda表达式。..._ptr(ptr) ,_pcount(new int(1)) {} //定制删除器 template //由于这个D是给函数模板用的,而不是给整个类用的 shared_ptr
= DefaultDeleter>class UniquePtr {private: T* ptr_; // 管理的原始指针 Deleter deleter_; /...= nullptr; }};// 数组版本的 operator[] 实现template Deleter>class UniquePtrDeleter...called\n"; delete p; });3.4 与多态结合使用unique_ptr 支持基类指针指向派生类对象,实现多态:struct Base { virtual...void foo() { std::cout 类析构函数必须为虚函数};struct Derived...无额外性能开销安全性:自动释放资源,提供异常安全保证灵活性:支持自定义删除器,适应不同资源管理需求在实际开发中,应优先考虑使用 unique_ptr 而非原始指针,只有在需要共享所有权时才考虑 std::shared_ptr