IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 智能指针的总结 -> 正文阅读

[C++知识库]智能指针的总结

定义

智能指针是对象,不是指针。它是通过c++的RAII机制实现的,主要是利用c++对象在释放资源的时候,会自动调用析构函数这一特性。

分类

auto_ptr: 智能指针,c++11已经停用;

shared_ptr: 强智能指针,可以改变资源的引用计数;

weak_ptr: 弱智能指针,不会改变资源的引用计数;

unique_ptr: 独占式强智能指针,只能转移,不能重新赋值;

智能指针的使用

shared_ptr

原理

shared_ptr采用了引用计数器,允许多个指针指向同一个对象。每一个shared_ptr的拷贝都指向相同的内存,并共同维护同一个引用计数器,记录统一使用被引用的次数。每增加一个shared_ptr智能指针对象,new对象指针的引用计数上就加1,当shared_ptr智能指针失效时,new对象指针的引用计数就减1。引用计数归0时,shared_ptr会释放管理的内存空间。

shared_ptr包含2个指针,一个是指向管理的内存空间,一个是指向内存的控制块。

内存控制块包含引用计数器,删除器,分配器等。

class Test
{
public:
    Test();
    ~Test();

    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }

    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }

private:
    std::shared_ptr<Test> m_father;
    std::shared_ptr<Test> m_son;
};

void test() {
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);

    ptr1->setFather(ptr2);
    ptr2->setSon(ptr1);

    //计数
    std::cout << ptr1.use_count() << endl;
    //计数
    std::cout << ptr2.use_count() << endl;

    //计数获取原始指针
    std::cout << ptr1.get() <<endl;
    std::cout << ptr2.get() <<endl;
}

输出:
Test Construct()
2
2
0xfe1740
0xfe1740

从输出信息中可以看到并未调用析构函数。主要是因为互相引用导致。

示例2 测试引用计数问题

//测试shared_ptr的引用计数
void testSharedPtrCount() {
    //不要使用该方式初始化
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);

    //计数
    std::cout << ptr1.use_count() << endl;
    std::cout << ptr2.use_count() << endl;

    std::shared_ptr<Test> ptr3(new Test());
    std::shared_ptr<Test> ptr4 = ptr3;

    //计数
    std::cout << ptr3.use_count() << endl;
    std::cout << ptr4.use_count() << endl;
}

输出:
1
1
2
2

可以看到使用同一个对象指针初始化的时候,引用计数为1,而使用智能指针初始化智能指针后,引用计数均为2。

智能指针的头文件为:#include

weak_ptr

weak_ptr不能单独作为智能指针使用,只能辅助shared_ptr解决循环依赖的问题。

定义对象的时候使用shared_ptr,引用对象的时候使用weak_ptr

修改shared_ptr的代码为:

class Test
{
public:
    Test();
    ~Test();

    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }

    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }

private:
    //修改对象的引用为weak_ptr
    std::weak_ptr<Test> m_father;
    std::weak_ptr<Test> m_son;
};

输出:
Test Construct()
1
1
0x1091740
0x1091740
Test Destruct()
Test Destruct()

可以看到析构函数被调用了。(即使析构了2次,部分编译器可能不会出现析构错误信息)

unique_ptr

unique_ptr是独占型的强智能指针。独占型就是不允许多个智能指针指向同一块内存空间,也不支持拷贝,复制。

示例1 独占性

//测试uniqueptr
void testUniquePtr() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);
    //编译期间就出现错误
    std::unique_ptr<Test> ptr2 = ptr1;

    std::cout << ptr1.get() << endl;
    std::cout << ptr2.get() << endl;
}

**示例2 move **

//测试unique_ptr的转移
void testUniquePtrMove() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);

    std::cout << "Ptr1: " << ptr1.get() << endl;

    std::unique_ptr<Test> ptr2(ps);
    ptr2 = std::move(ptr1);

     std::cout << "Ptr1: "  << ptr1.get() << endl;
     std::cout << "Ptr2: "  << ptr2.get() << endl;
}

//输出
Test Construct()
Ptr1: 0x761740
Test Destruct()
Ptr1: 0
Ptr2: 0x761740
Test Destruct()

可以看出调用move()后,ptr1被置为nullptr(0), ptr2被设置为0x761740

常见的陷阱

  • 不要使用指针初始化多个智能指针。

  • 不要delete get()返回的指针。

总结

  1. 智能指针是对象而不是指针。
  2. 智能指针解决的是动态内存管理的问题(堆内存)。
  3. shared_ptr的循环依赖问题通过weak_ptr来解决,weak_ptr不拥有对象的所有权,一个share_ptr可对应多个weak_ptr
  4. unique_ptr可算作auto_ptr的翻版,不允许多个unique_ptr持有同一个对象。
  5. auto_ptr已经被弃用。

参考地址

C++ 智能指针

c++智能指针

C++智能指针的使用(非常详细)

C++智能指针详解

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 07:51:17  更:2022-05-08 07:54:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 0:07:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码