相关文章推荐
豪情万千的眼镜  ·  智能指针reset()·  2 天前    · 
豪情万千的眼镜  ·  Resources·  1 月前    · 
豪情万千的眼镜  ·  python 调用打印机 ...·  9 月前    · 
豪情万千的眼镜  ·  [Answer]-How to ...·  9 月前    · 
豪情万千的眼镜  ·  Java ...·  11 月前    · 
豪情万千的眼镜  ·  MySQL 导出数据 | ·  11 月前    · 
难过的打火机  ·  使用 If...Then...Else ...·  1小时前    · 
温文尔雅的生姜  ·  mssql sqlserver ...·  1小时前    · 

智能指针reset()方法分析

reset()函数接受一个可选参数,这个参数可以是一个指向新对象的指针,也可以是一个空指针。

当参数为空指针时,reset()会释放原来指针所管理的资源,同时将指针置为空。当参数为非空指针时,

reset()会先释放原来指针所管理的资源,然后将指针重新指向新对象,

此时此刻,如果有其它智能指针也指向它,只是计数减一。

当使用reset函数时,智能指针的引用计数会相应地减少1。如果减少后引用计数变为0,则表示该资源不再被使用,可以安全地删除资源。

可以通过下面的代码去调试理解:

#include <iostream>
#include <functional>
#include <memory>
#include <thread>
class A{
    public:
    A(int x) : _x(x){
        std::cout << " create " << _x << std::endl;
    ~A(){
        std::cout << " release " << _x << std::endl;
    int _x;
void testshared_ptr_Reset(){
    std::shared_ptr<A> p(new A(1));  // 这里create A(1)
    std::cout << p.use_count() << "   p.get() = " << p.get() << __LINE__ << std::endl;
    std::cout << p.get() << "   " << __LINE__ << std::endl;
    auto p2 = p;
    auto p21 = p;
    std::cout << p.use_count() << "   " << __LINE__ << std::endl;
    p.reset();
    p.reset();
    p.reset(); //多次reset,A(1)的引用次数只减少了1,
    std::cout << p2.use_count() << "   << p2.get() = " << p2.get() << __LINE__ << std::endl;  // p2.get() == p1.get()
    auto p3 = p;
    std::cout << p.use_count() << "   " << __LINE__ << std::endl;
    std::cout << p3.use_count() << "   " << __LINE__ << std::endl;
    auto p4 = p;
    std::cout << p.use_count() << "   " << __LINE__ << std::endl;
    p.reset(new A(2)); // 这里create A2
    std::cout << p.use_count() << "   " << __LINE__ << std::endl;
    std::cout << p3.use_count() << "   " << __LINE__ << std::endl;
    // 退出的时候释放两次实例 A2 A1

智能指针循环

这是不推荐的,不要同时你中有我,我中有你,即:A的成员智能指针指向B,B的成员智能指针指向A

相互持有的时候,两边的析构函数都没有被调用到,造成内存泄漏。

这时候可以同weak_ptr来解决,它指向智能指针sp,但是并不持有引用计数,即sp的use_count()不会增加。

weak_ptr用法

接续前面的代码,weak_ptr的 lock, expired, use_count 三个函数了解它

std::weak_ptr<A> gw;
void TestWeakPtr(){
    gw.lock();
    std::this_thread::sleep_for(std::chrono::seconds(5));
    if(gw.expired()){
        std::cout << "wb lock gp success !" << std::endl;    
    } else {
        std::cout << "wb lock gp failed !" << std::endl;    
int main(){
    std::shared_ptr<A> sp(new A(3));
    gw = sp;
    std::cout << " gw.use_count() = " << gw.use_count() << " sp.use_count() = " << sp.use_count() << std::endl;
    std::thread ([&](){
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << " sp reset \n";
        sp.reset();
    }).detach();
    TestWeakPtr(); // 测试A(3)的资源使用情况
    std::cout << " gw.use_count() = " << gw.use_count() << " sp.use_count() = " << sp.use_count() << std::endl;
    return 0;

 create 3
 gw.use_count() = 1 sp.use_count() = 1  //增加了gw对sp的应用,但是sp的use_count()没有增加
 sp reset
 release 3
wb lock gp success !
 gw.use_count() = 0 sp.use_count() = 0

当使用reset函数时,智能指针的引用计数会相应地减少1。如果减少后引用计数变为0,则表示该资源不再被使用,可以安全地删除资源。当参数为空指针时,reset()会释放原来指针所管理的资源,同时将指针置为空。当参数为非空指针时,reset()函数接受一个可选参数,这个参数可以是一个指向新对象的指针,也可以是一个空指针。reset()会先释放原来指针所管理的资源,然后将指针重新指向新对象,此时此刻,如果有其它智能指针也指向它,只是计数减一。
C++智能指针 ⼀ ⼀. 智能指针 智能指针C++ 中,我们申请内存⼀般使⽤ new,释放内存时使⽤ delete,但是有时候我们可能由于疏忽会忘记 delete,或者当程序有多个 出⼝时,也会容易有 new 没有 delete,这样就产⽣了内存泄漏,如果你的程序是⼀个需要长期运⾏的服务器程序,可能运⾏着⼏天突然程 序就崩溃了,原因也不好定位,所以为了⽅便内存管理,C++ 引⼊了智能指针智能指针的优点在于能够帮助程序员⾃动释放我们 new 出 来的堆内存。 C++ 标准库有四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr(auto_ptr 是 C++98 标准的,其余都是 C++11 标准推出的,auto_ptr 现在已经不再使⽤了),C++11 这三种智能指针都是类模板。 ⼆ ⼆. shared_ptr (⼀)概述 (⼀)概述 shared_ptr 是⼀个共享式指针,所有的 shared_ptr 共享对指向内存的所有权,不是被⼀个 shared_ptr 拥有,⽽是多个 shared_ptr 之间互相协作。 (⼆)⼯作原理 (⼆)⼯作原理 引⽤计数,use_count 为 0 时就释放对象空间。 (三)初始化 (三)初始化 如果是定义了⼀个智能指针却不初始化,shared_ptr<int> p1,代表定义了⼀个指向 int 类型对象的智能指针但是⽬前指向为 empty。推荐使⽤ make_shared 函数来初始化 shared_ptr,它是标准库的函数模板,安全,⾼效地分配和使⽤ shared_ptr。 shared_ptr<int> pint = make_shared<int>(100); shared_ptr<string> pstr = make_shared<string>(5,'a'); 也可以使⽤直接初始化的⽅式 shared_ptr<int> pint(new int(100)) 来创建⼀个 shared_ptr 并初始化,但是由于 shared_ptr 定义 的构造函数是 explicit 的,因此不能使⽤ shared_ptr<int> pint = new int(100) 来创建⼀个 shared_ptr 并初始化,因为这种⽅式隐式要 求将⼀个普通的 int * 转换为 shared_ptr<int>。 (四)常⽤操作 (四)常⽤操作 1. use_count 返回多少个智能指针指向该对象,主要⽤于调试。 2. unique 判断该智能指针是否独占该内存,如果该智能指针不指向任何对象,判断 unique 的时候也是假。 3. reset 不带参数时:放弃指针对对象的掌管权,重置为 nullptr 带参数时:参数⼀般是⼀个 new 的空间,相当于放弃指针对当前对象的掌管权,然后将指针指向 new 出来的空间。 4. * 解引⽤,可以获取指针指向的对象。 5. get 获取指针指针⾥保存的裸指针,⼀般⽤于⼀些接⼝需要使⽤到 C 语⾔指针的情况。 6. swap 交换两个智能指针所指的对象。 7. =nullptr 该智能指针指向 nullptr,代表解除对该对象的掌握权,引⽤计数将会减1,如果此时该内存空间的引⽤计数变为0,会同时释放该内存。 8. 指定删除器以及删除数组问题 指定删除器以及删除数组问题 智能指针能在⼀定时机帮我们删除所指向的对象,使⽤ delete 作为默认的资源析构⽅式,我们也可以指定⾃⼰的删除器取代系统提供的默 认删除器,当智能指针需要删除所指向的对象时,编译器就会调⽤我们提供的删除器。 shared_ptr 指定删除器的⽅法⽐较简单,⼀般只需要在参数中添加具体的删除器函数即可。如果提供了删除器,那么就需要⼿动删除资 源,否则会造成内存泄漏。删除器函数可以是函数,lambda 表达式,重载了 operator() 的类等。 还可以使⽤ default_delete 来做删除器,default_delete 是标准库⾥的⼀个模板类。如:shared_ptr<A> p3(new A[10], default_delete<A[]>()),这样就知道我们使⽤智能指针指向了⼀个对象数组,这样就可以正确释放了。 其实,使⽤ shared_ptr 指向对象数组不需要通过删除器的⽅式,只需要在定义 shared_ptr 时指为数组类型即可,如:shared_ptr<A[]> p4(new A[10])。 额外说明:就算是两个 shared_ptr 指定了不同的删除器,只要他们指向的对象类型相同,那么这两个 shared_ptr 也是同⼀个类型,可以 放到同⼀个容器去,vector<shared_ptr<int>> pvec{p1,p2}。 三 三
auto_ptr与unique_ptr的比较 先介绍unique_ptr(独占智能指针)参考爱编程的大丙 std::unique_ptr 是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,可以通过它的构造函数初始化一个独占智能指针对象,但是不允许通过赋值将一个 unique_ptr 赋值给另一个 unique_ptr。 // 通过构造函数初始化对象 unique_ptr<string> ptr1(new string(“aaa”)); // error, 不允许将一个uni
公司里小组组织c++知识的分享会,正好我手上碰到过几个purify的内存泄露问题,就借这里总结一下c++的内存问题。   借鉴陈硕总结的分类,c++大致的内存问题有以下几个方面:   1.缓冲区溢出   在使用自己编写的缓冲区或者使用不安全的函数时,会遇到类似数组越界的缓冲区溢出问题,Linux内核的解决办法是栈随机化,金丝雀的检测,具体的攻击手段和例子,可以参考我另一篇的buffer lab
unique_ptr和shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定的对象。初始化没有类似make_shared的标准库函数返回一个unique_ptr,需要将其绑定到一个new返回的指针上。 unique_ptr<int> u(new int(1024)); 由于unique_ptr拥有它所指向的对象,所以他不支持普通的拷贝和赋值操作。 unique_ptr
智能指针的 `reset` 函数是用于重置智能指针所管理的对象。当调用 `reset` 函数时,智能指针会释放当前管理的对象,并接管新的对象的所有权。具体来说,它会将智能指针内部的指针设置为新对象的地址,并且会释放旧对象的内存(如果有的话)。 下面是一个示例代码: ```cpp #include <iostream> #include <memory> int main() { std::shared_ptr<int> ptr1 = std::make_shared<int>(42); std::cout << *ptr1 << std::endl; // 输出:42 ptr1.reset(new int(24)); std::cout << *ptr1 << std::endl; // 输出:24 return 0; 在上面的示例中,我们首先创建了一个 `std::shared_ptr` 对象 `ptr1`,并将其指向一个动态分配的整型对象。然后,我们通过 `reset` 函数将 `ptr1` 的指针重置为一个新的动态分配的整型对象。最后,我们通过 `*ptr1` 访问智能指针所管理的对象,并将其输出到控制台上。 需要注意的是,当调用 `reset` 函数时,智能指针会自动释放旧对象的内存。如果智能指针之前没有管理任何对象或者已经重置过了,那么 `reset` 函数就不会有实际的操作。
 
推荐文章