首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

现代C++之手写智能指针

如果你觉得这个实现很别扭的话,也恭喜你,因为 C++ 委员会也是这么觉得的:auto_ptr 在 C++17 时已经被正式从C++ 标准里删除了。 上面会导致什么问题呢?...类似,采用栈上的指针去管理堆上的内容,从而使得堆上的对象随着栈上对象销毁时自动删除; 2)scoped_ptr有着更严格的使用限制——不能拷贝,这也意味着scoped_ptr不能转换其所有权,所以它管理的对象不能作为函数的返回值...析构函数,生成规则和C++98一样,在C++11中有点不同的是,析构函数默认是noexcept。 拷贝构造函数,用户自定义了移动操作会导致不生成默认的拷贝构造函数,其它和C++98的行为一致。...// 在析构函数中,会先判断该临时对象的是否指向资源,如果没有,析构结束。否则,对引用计数减1,判断引用计数是否为0,如果为0,删除共享引用计数指针,否则不操作。...在析构函数中,会先判断该临时对象的是否指向资源,如果没有,析构结束。否则,对引用计数减1,判断引用计数是否为0,如果为0,删除共享引用计数指针,否则不操作。

2.9K10

std::shared_ptr 的线程安全性 & 在多线程中的使用注意事项

std::shared_ptr 是个类模版,无法孤立存在的,因此实际使用中,我们都是使用他的具体模版类。...这里使用 std::shared_ptr 来举例,我们讨论的时候,其实上是在讨论 std::shared_ptr 的线程安全性,并不是 SomeType 的线程安全性。...那我们在讨论某个操作是否线程安全的时候,也需要看具体的代码是作用在 std::shared_ptr 上,还是 SomeType 上。...() 函数是否线程安全,这里显示是非线程安全的,因为对 some_value 的操作没有加锁,也没有使用 atomic 类型,多线程访问就出现未定义行为(UB) std::shared_ptr 线程安全性...如果确实需要在多线程环境下对同一 std::shared_ptr 实例做 swap () 操作,可以调用 atomic 对 std::shared_ptr 的重载函数,如: template< class

2.7K10
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr 、shared_ptr 、weak_ptr 源码分析)

    boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为 函数的返回值)。...如果你的C++基础比较好,可以想到拷贝构造函数跟构造函数一样,如果有对象成员是需要先构造对象成员的(这一点 也可以从调用堆栈上看出),故可以在shared_count 类的拷贝构造函数设置断点,然后就可以跟踪进去...说到这里,我们也可以明白,即使最后没有调用p2.reset(); 当p2 栈上对象生存期到, 需要调用shared_ptr 类析构函数,进而调用shared_count 类析 构函数,所以执行的结果也是跟...强引用与弱引用: 强引用,只要有一个引用存在,对象就不能释放 弱引用,并不增加对象的引用计数(实际上是不增加use_count_, 会增加weak_count_);但它能知道对象是否存在 通过weak_ptr...访问对象的成员的时候,要提升为shared_ptr 如果存在,提升为shared_ptr(强引用)成功 如果不存在,提升失败 对于上述的例子,只需要将Parent 类里面的成员定义改为如下,

    1.4K30

    C++智能指针原理和实现

    智能指针主要思想是RAII思想,“使用对象管理资源”,在类的构造函数中获取资源,在类的析构函数中释放资源。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。   ...;   3.析构函数中完成资源的清理,可以保证资源的正确初始化和释放;   4.如果对象是用声明的方式在栈上创建局部对象,那么RAII机制就会正常工作,当离开作用域对象会自动销毁而调用析构函数释放资源。...的对象所有权是独占性的,使用拷贝构造和赋值操作符时,会造成对象所有权的转移,被拷贝对象在拷贝过程中被修改;   (3) 基于第二条,因此不能将auto_ptr放入到标准容器中或作为容器的成员;   (4...交换: std::swap(std::shared_ptr) 特化的swap算法用于交换两个智能指针。   ...交换:std::swap(std::weak_ptr) 特化的swap算法用于交换两个智能指针。 注意事项:   (1) 不能将指针直接赋值给一个智能指针,一个是类,一个是指针。

    55730

    从零开始学C++之boost库(一):详解 boost 库智能指针

    boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为 函数的返回值)。...本想跟踪shared_ptr 的拷贝构造函数,在当行设置断点后F11直接跳过了,说明是shared_ptr类没有实现拷贝构造函数,使用的是编译器默认的拷 贝构造函数,那如何跟踪呢?...如果你的C++基础比较好,可以想到拷贝构造函数跟构造函数一样,如果有对象成员是需要先构造对象成员的(这一点 也可以从调用堆栈上看出),故可以在shared_count 类的拷贝构造函数设置断点,然后就可以跟踪进去...说到这里,我们也可以明白,即使最后没有调用p2.reset(); 当p2 栈上对象生存期到, 需要调用shared_ptr 类析构函数,进而调用shared_count 类析 构函数,所以执行的结果也是跟...强引用与弱引用: 强引用,只要有一个引用存在,对象就不能释放 弱引用,并不增加对象的引用计数(实际上是不增加use_count_, 会增加weak_count_);但它能知道对象是否存在 通过weak_ptr

    6.7K20

    从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr 、shared_ptr 、weak_ptr 源码分析)

    boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为 函数的返回值)。...本想跟踪shared_ptr 的拷贝构造函数,在当行设置断点后F11直接跳过了,说明是shared_ptr类没有实现拷贝构造函数,使用的是编译器默认的拷 贝构造函数,那如何跟踪呢?...如果你的C++基础比较好,可以想到拷贝构造函数跟构造函数一样,如果有对象成员是需要先构造对象成员的(这一点 也可以从调用堆栈上看出),故可以在shared_count 类的拷贝构造函数设置断点,然后就可以跟踪进去...说到这里,我们也可以明白,即使最后没有调用p2.reset(); 当p2 栈上对象生存期到, 需要调用shared_ptr 类析构函数,进而调用shared_count 类析 构函数,所以执行的结果也是跟...强引用与弱引用: 强引用,只要有一个引用存在,对象就不能释放 弱引用,并不增加对象的引用计数(实际上是不增加use_count_, 会增加weak_count_);但它能知道对象是否存在 通过weak_ptr

    1.7K00

    【C++】简单实现C++11的三种智能指针

    中 std::weak_ptr为了解决循环引用的问题而提出, 类似std::shared_ptr但是不会增加引用计数. std::weak_ptr没有*和->因此不能操作资源, .expired()可以检查目标资源是否被释放..., 若释放则返回true. .lock()在资源未释放的时候返回一个新的std::shared_ptr, 否则返回nullptr 智能指针的释放依赖于作用域, 所以当需要使用更大的生命周期时还是应该考虑手动管理或者在更大的作用域中使用智能指针...但是垃圾回收器的分析和执行仍然有很大的代价 垃圾回收器有时候会遇到缓存优化的问题, 而且回收的时间可能会造成停顿, 智能指针在这点上表现更好, 可以实时处理 垃圾回收器一般在单独的线程中执行, 而智能指针的回收在当前线程的析构函数中执行...的shared_ptr 这个问题是由于非侵入式访问的标准库设计哲学, shared_ptr的计数器和对象本身是分离的, 如果在类中对this构造一个shared_ptr, 那么产生的是第二个计数器, 和初始化两次...因此在类中这个构造函数结束后, 这个对象(自己)就会被调用析构, 然后一切都boom了 enable_shared_from_this则通过weak_ptr安全地生成了一个自己的shared_ptr,

    1.9K20

    C++ 智能指针(unique_ptr, 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...,当函数退出时,t调用析构函数时, 也就是最后一个对象调用析构函数时,如果t.p不是空指针时,会调用p指向内存类型的删除器。...() { deleter(p); } 和shared_ptr的析构函数不同,unique_ptr的析构函数更简单, 只需要调用类型T的析构函数,如果是自定义类型需要重写deleter template...unique_ptr的p置为nullptr,但是会返回这块地址。

    2.7K32

    CC++开发基础——智能指针

    ,都需要在堆中申请一段内存,然后在函数的最后释放该内存。...但是当函数运行期间出现异常的时候,delete将不被执行,此时申请到的内存得不到释放,会发生内存泄露。智能指针由于是类对象,该类对象可以在析构的时候自动释放智能指针所指向的内存。...因此,如果此时使用智能指针代替原始指针,可以不用手动调用"delete/delete []",智能指针指向的堆内存会自动被释放。...智能指针常用的类模板有: std::unique_ptr std::shared_ptr std::weak_ptr 由上述的类模板可以生成三种类型的智能指针实例。...如果必须要使用new/delete,可以考虑以下措施来避免: 1.尽可能使用栈内存 栈内存不会造成内存泄露,且资源一旦超出栈的使用范围就会被销毁。

    48020

    【C++】基础:Effective C++高效编程建议

    使接口易于正确使用,而难以错误使用 好的接口易于正确使用,而难以错误使用。你应该在你的所有接口中为这个特性努力。 使易于正确使用的方法包括在接口和行为兼容性上与内建类型保持一致。...当类型转换应该用于所有参数时,声明为非成员函数 如果你需要在一个函数的所有参数(包括被 this 指针所指向的那个)上使用类型转换,这个函数必须是一个非成员函数。 25....考虑支持不抛异常的 swap 如果 std::swap 对于你的类型来说是低效的,请提供一个 swap 成员函数。并确保你的 swap 不会抛出异常。...如果你提供一个成员 swap,请同时提供一个调用成员 swap 的非成员 swap。对于类(非模板),还要特化 std::swap。...调用 swap 时,请为 std::swap 使用一个 using declaration,然后在调用 swap 时不使用任何 namespace 限定条件。 26.

    22210

    【笔记】《Effective C++》条款1-25

    delete, 此时基类没有虚析构函数, 那么此时这个对象实际上会调用基类的析构函数(因为没有多态), 于是整个内存的回收是不完全的, 会导致一个局部销毁的对象从而引发内存泄漏 最好的解决方法就是对于任何一个将要用来继承的类都实现虚析构函数...weak_ptr: 不参与引用计数, 与shared_ptr一起使用 14 在资源类中小心Copying行为 这一条是当你不得不自己建立资源管理类的时候要注意的 如果对RAII进行复制是不合理的, 那么就应该禁止它...这个版本的swap可以有复杂的偏特化 再在std命名空间中提供一个只关于类本身(不允许是模板类)的swap特化, 同样调用我们的成员swap....不允许是模板类是因为std的设计协议就是不要为std添加任何额外的模板, 函数, 类等等, 我们只允许添加新的模板特化版本 最后在我们需要调用swap的时候, 先using std::swap;暴露出std...的swap, 这样编译器进行函数搜索的时候会优先查找当前命名空间的swap, 找不到时会再去找std的swap

    1.1K30

    《Effective C++》读书笔记(4):设计与声明

    shared_ptr还有个性质是会使用每个指针专属的删除器。...如果对象在一个DLL中被new创建而在另一个DLL内被delete,会引起运行期错误;而shared_ptr使用的删除器来自创建时所在的DLL,不存在上述问题。...如果对于你的类/模板类来说,swap的默认实现的效率可接受,那么无需额外做什么;而如果默认实现的效率不足,通常源于类为了二进制兼容性使用了pimpl技法,就需要实现一个确保不抛出异常的swap:...2、在类/模板类所在的命名空间提供一个non-member的swap,调用swap成员函数。 3、对于类(而非模板类),还需特化std::swap,调用swap成员函数。...4、真正使用swap时先声明using std::swap,再直接使用swap,让编译器寻找最合适的swap实现版本。

    20730

    C++智能指针

    即我们实际上把管理一份资源的责任托管给了一个对象 好处: 不需要显式地释放资源 对象所需的资源在其生命期内始终保持有效 示例: // 使用RAII思想设计的SmartPtr类 template...:只声明不实现+声明成私有;C++11防拷贝的方式修饰函数为delete 5、std::shared_ptr 概念及介绍: C++11中开始提供更靠谱的并且支持拷贝的shared_ptr shared_ptr...在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源 如果不是0,就说明除了自己还有其他对象在使用该份资源..._ptr); std::swap(_pCount, sp._pCount); std::swap(_mtx, sp...._ptr); std::swap(_pCount, sp._pCount); std::swap(_mtx, sp.

    62020

    《Effective C++》读书笔记(5):实现

    过早地声明某对象,如果因为种种原因(条件分支、过早返回、异常等)没有使用该对象,那么不仅降低了程序的清晰度,还浪费了上述的构造、析构的成本。...= ptrs.end(); ++iter){ (*iter)->f(); } //或者将f()实现为虚函数,则也无需转型 如果转型是必要的,试着将它隐藏于某函数背后;用户调用该函数而不是使用转型...---- 条款29、为“异常安全”而努力是值得的 抛出异常时,异常安全的函数会不泄露任何资源、不允许数据败坏。函数的“异常安全保证”等于所调用的各个函数的“异常安全保证”中的最弱者。...; }; ---- 条款30、透彻了解inlining的里里外外 将大多数inlining限制在小型、被频繁调用的函数身上。...提供一个抽象基类,目的是描述派生类的接口,因此它不提供成员变量、构造函数,只提供虚析构函数与一组纯虚函数来描述所有接口。

    20320

    C++的智能指针unique_ptr、shared_ptr和weak_ptr

    ①unique_ptr 在C++中,unique_ptr是一个智能指针(smart pointer)类模板,用于管理动态分配的内存资源,它提供了自动释放内存的功能。...②shared_ptr 在C++中,shared_ptr是一个智能指针(smart pointer)类模板,用于管理动态分配的内存资源。...每次拷贝会增加引用计数。当引用计数变为0时,表示没有任何shared_ptr指向该内存,会释放内存。 循环引用问题:如果存在循环引用(两个或多个对象相互持有shared_ptr),会导致内存泄漏。...通过弱引用指针,我们可以在需要时使用lock()函数获取一个有效的shared_ptr来操作对象,一旦对象的引用计数变为0,弱引用指针将自动失效。...判断是否有效:可以使用 expired() 函数来检查 weak_ptr 是否已经失效,即所观察的 shared_ptr 是否已经被释放。

    1.1K20

    boost的信号槽原理和实践

    这里我觉得在一些场景下,boost signal2也是不错的选择。...然后,用于处理槽列表以及从槽标识符到连接的映射的所有代码都被分解到signal_base 专门处理any和 function对象的类中,使用众所周知的 pimpl 惯用法隐藏实际实现。..."pull" 模式可以保存combiner's state在栈上和, 新数据来的时候,过来一下数据。相反“push" 模式需要combiner保存各个状态,如果slots过多,会是不小的开销。...原来的Boost.Signals 使用boost::signals::trackable派生类。 由于boost::signals::trackable派生类的析构函数顺序先于base类的析构函数。...在多线程环境中,如果一个object在一个线程被析构了,另一个线程的signal会call到摧毁的object。 signal2使用了shared_pt机制来解决这个问题。

    46710

    C++ 新特性学习(一) -- 概述+智能指针(smart_ptr)

    C++ 0x/11 终于通过了,真是个很爽的消息。于是乎我决定对新的东西系统学习一下。 首先当然要从tr1开始,智能指针实际上我已经用过很多次了,但是为了完整起见,还是写出来记录一下。...如果表达式e是一个函数,那么就是这个函数返回值的类型。 如果不符合1和2,如果e是左值,类型为T,那么decltype(e)是T&;如果是右值,则是T。...这段代码支持GNU-C++、VC++,如果电脑里的C++版本不够则会导入BOOST里的智能指针库,这时候要安装BOOST库,贴完这一段,就可以使用神奇的std::shared_point了。...另外智能指针上还有个重要的东西叫std::weak_ptr,这是智能指针的一个监视器,内部不会改变引用技术,但是可以用于获取智能指针,当资源正常时lock函数会返回智能指针,当资源被释放了后会产生空指针...另外,使用智能指针必须注意的两点: 避免引用成环 引用成环会导致引用计数永不为0,造成内存泄漏,比如在类a,b,c里,各有一个成员变量p,使得a.p = &b, b.p = &c, c.p = &a;

    37020

    C++ 新特性学习(一) -- 概述+智能指针(smart_ptr)

    C++ 0x/11 终于通过了,真是个很爽的消息。于是乎我决定对新的东西系统学习一下。 首先当然要从tr1开始,智能指针实际上我已经用过很多次了,但是为了完整起见,还是写出来记录一下。...如果表达式e是一个函数,那么就是这个函数返回值的类型。 如果不符合1和2,如果e是左值,类型为T,那么decltype(e)是T&;如果是右值,则是T。...这段代码支持GNU-C++、VC++,如果电脑里的C++版本不够则会导入BOOST里的智能指针库,这时候要安装BOOST库,贴完这一段,就可以使用神奇的std::shared_point了。...另外智能指针上还有个重要的东西叫std::weak_ptr,这是智能指针的一个监视器,内部不会改变引用技术,但是可以用于获取智能指针,当资源正常时lock函数会返回智能指针,当资源被释放了后会产生空指针...另外,使用智能指针必须注意的两点: 避免引用成环 > 引用成环会导致引用计数永不为0,造成内存泄漏,比如在类a,b,c里,各有一个成员变量p,使得a.p = &b, b.p = &c, c.p = &

    57910

    C++11 智能指针:优化资源管理,规避内存泄漏的利器

    在c++中智能指针是为了防止我们的程序中出现内存泄漏而设计出来的一个类模板,用于管理我们在程序中动态分配的内存,它的行为与常规的指针类似,但提供了自动内存管理的功能,能够有效避免内存泄漏、悬空指针等问题...在 C语言或者C++ 中,当我们使用 malloc或 new等函数动态分配内存后,如果没有使用free或delete释放资源,就可能会发生内存泄漏。..._year); std::swap(_month, d2._month); std::swap(_day, d2....1,程序结束后n1和n2管理的资源也正常释放,ListNode的析构函数 调用两次,n1和n2析构后,节点中的weak_ptr会检查所绑定shared_ptr的引用计数,如果为0,会自动调用析构函数释放...在使用shared_ptr时,需要注意对象的访问和修改是否在多个线程中同时进行,以及在析构对象时是否存在资源竞争等问题.

    13710
    领券