C++11 智能指针详解

xiaoxiao2025-07-23  31

// // SmartPointer.cpp // test_cpp_protocol_01 // // Created by jeffasd on 2016/10/24. // Copyright © 2016年 jeffasd. All rights reserved. // #include "SmartPointer.h" #include <stdio.h> #include <memory.h> #include <string> #include "Person.h" SmartPointer::SmartPointer() :_data(3) { printf("SmartPointer constructor\n"); _data = int(3); } SmartPointer::~SmartPointer() { printf("SmartPointer destructor\n"); } void SmartPointer::showName() { printf("smartPointer showName\n"); // 智能指针的各种初始化方法 std::shared_ptr<int> sharedPtr = std::make_shared<int>(3); std::shared_ptr<Student> sharedPtrOne(new Student()); std::shared_ptr<Student> sharedPtrTwo = std::make_shared<Student>(); sharedPtrTwo->writeWorldWithString("hello wolrd"); std::shared_ptr<Student> _imp = std::shared_ptr<Student>(new Student()); std::shared_ptr<Student> sharedPtrThree(sharedPtrOne); // copy 引用计数+1 /** 每个shared_ptr都有一个关联的计数值,通常称为引用计数。无论何时我们拷贝一个shared_ptr,计数器都会递增。 例如,当用一个shared_ptr初始化另一个shred_ptr,或将它当做参数传递给一个函数以及作为函数的返回值时,它 所关联的计数器就会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的 shared_ptr离开其作用域)时,计数器就会递减。一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理 的对象。 */ Student *xiaoming = new (std::nothrow) Student (); Student *xiaohua = new (std::nothrow) Student (); // 注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存 std::shared_ptr<Student> sharedPtrFive(xiaoming); // 当一个对象指针使用智能指针时 以后不要再使用此对象指针 而要使用智能指针 // warring 对一个原始指针初始化多个shared_ptr,会造成二次释放同一个内存,此用法不正确 // std::shared_ptr<Student> sharedPtrErrorUse(xiaoming); xiaoming->writeWorldWithString("hello xiaoming"); // 使用智能指针之后最好不要再使用原始指针 不推荐这样用 //返回与sharedPtrFive共享xiaoming对象的智能指针数量,这个操作可能会比较慢,一般调试的时候用,正式情况下一般不用 //一个bool函数 如果只有一个引用计数则返回true,如果不是则返回false bool isUnique = sharedPtrFive.unique(); printf("sharedPtrFive is Unique %s", isUnique ? "true" : "false"); // use_count()获取有多少个智能指针共享同一个内部数据指针 printf("reference is %ld\n", sharedPtrFive.use_count()); // shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。 // 初始化。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如std::shared_ptr<int> p4 = new int(1);的写法是错误的 // 拷贝和赋值根据是否有新的智能指针指向了同一个对象,如果有新增智能指针指向了同一个对象,引用计数加1 否则引用计数不加1 // 注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存 // 注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环,循环引用会导致堆内存无法正确释放,导致内存泄漏。 // 拷贝和赋值根据是否有新的智能指针指向了同一个对象,如果有新增智能指针指向了同一个对象,引用计数加1 否则引用计数不加1 // 有新的sharedPtrSix指向了xiaoming对象 引用计数加1 std::shared_ptr<Student> sharedPtrSix = sharedPtrFive; // copy 赋值 引用计数+1 // std::shared_ptr<Student> sharedPtrSix(sharedPtrFive); // copy 赋值 引用计数+1 // use_count 引用计数详解:指的是有多少个shared_ptr指向同一个对象 此处use_count为2 sharedPtrSix和sharedPtrFive 均指向xiaoming对象 // 没有新的智能指针指向了xiaoming对象 引用计数不加1 sharedPtrFive = sharedPtrSix; printf("reference is %ld\n", sharedPtrFive.use_count()); printf("reference is %ld\n", sharedPtrSix.use_count()); sharedPtrFive->writeWorldWithString("sharedPtrFive"); sharedPtrSix->writeWorldWithString("sharedPtrSix"); // 重新赋值 // sharedPtrFive.reset(xiaohua); sharedPtrFive.reset(); // 将sharedPtrFive的引用计数减一 引用计数最小值为0 sharedPtrFive.reset(); // 将sharedPtrFive的引用计数减一 引用计数最小值为0 sharedPtrFive.reset(); // 将sharedPtrFive的引用计数减一 引用计数最小值为0 printf("reference is %ld\n", sharedPtrFive.use_count()); printf("reference is %ld\n", sharedPtrSix.use_count()); sharedPtrSix.reset(); // 将sharedPtrSix的引用计数减一 引用计数最小值为0 // unique_ptr是一个独占的智能指针,即unique_ptr不支持复制,但是支持通过move转移内部指针 // Student *xiaogang = new (std::nothrow) Student (); // std::unique_ptr<Student> uniquePtr(xiaogang); std::unique_ptr<Student> uniquePtr = std::make_unique<Student>(); std::unique_ptr<Student> uniquePtrOne = std::make_unique<Student>(); // release()释放原来智能指针指向的指针,只负责转移控制权,不负责释放内存,常见的用法 // 所以如果单独用: 则会导致uniquePtr丢了控制权的同时,原来的内存得不到释放 // uniquePtr.release() // 注意release()只转移控制权,并不释放内存,而reset和=nullptr操作会释放原来的内存 // uniquePtr.reset();// 释放p原来的对象,并将其置为nullptr, uniquePtr = nullptr; // 等同于uniquePtr.reset(); uniquePtr = std::move(uniquePtrOne); // 转移控制权 printf("reference \n"); // weak_ptr可以看做shared_ptr的助手,weak_ptr要和shared_ptr配套一起使用。当创建一个weak_ptr时,要用一个shared_ptr来初始化它。 // 复制shared_ptr是会增加内部数据的引用计数,但是复制weak_ptr时,以及由shared_ptr构造weak_ptr时,是不会增加引用计数的;且weak_ptr没有重载*、->操作符,所以不能通过*、->操作符操作智能指针的内部数据 /** 因为weak_pt不增加引用计数,我们可以任意构造weak_ptr,任意释放weak_ptr,却不会影响智能指针中内部数据的释放(内部数据何时释放,只取决于shared_ptr)。那么weak_ptr有什么用呢?weak_ptr可以用来监看shared_ptr: weak_ptr::use_count()查看有多少个shared_ptr共享同一个内部数据 weak_ptr::expired判断shared_ptr是否有效,即shared_ptr内部数据是否被释放 weak_ptr是否可以监看shared_ptr中的内部数据呢?因为weak_ptr是弱指针,所以不能直接访问,但是可以通过weak_ptr::lock间接访问。 */ std::shared_ptr<Student> sharedPtrSeven = std::make_shared<Student>(); std::weak_ptr<Student> weakPtr = sharedPtrSeven; printf("weak_ptr reference is %ld\n", weakPtr.use_count()); // 相当于把weak_ptr转换为shared_ptr,然后通过shared_ptr去访问。 std::shared_ptr<Student> sharedPtrLock = weakPtr.lock(); // 将lock返回的智能指针赋值给sharedPtrLock 引用计数会加1 printf("weak_ptr reference is %ld\n", weakPtr.use_count()); printf("sharedPtr reference is %ld\n", sharedPtrSeven.use_count()); weakPtr.lock(); // 没有将lock函数返回的智能指针赋值给任何其他智能指针 引用计数不会加1 printf("weak_ptr reference is %ld\n", weakPtr.use_count()); printf("sharedPtr reference is %ld\n", sharedPtrSeven.use_count()); printf("reference"); }

 

转载请注明原文地址: https://www.6miu.com/read-5033603.html

最新回复(0)