赞
踩
要介绍智能指针需要先搞明白为什么需要它。
普通指针存在一个比较重要的问题就是我们在动态分配内存后,有可能会忘记调用delete去释放内存或者说在释放内存代码的前面发生了异常导致释放内存的代码不能执行,那这就会导致这部分内存无法被回收和再次使用,从而造成系统资源浪费 其实也就是内存泄漏。
智能指针是在 头文件中的 std 命名空间中定义的
智能指针实际上是使用了RAII原理(Resource Acquisition Is Initialization)资源获取即初始化,我们通过在对象的构造函数中获取资源并在析构函数中释放资源,这样来确保资源在不再需要时被及时释放,从而避免资源泄漏。
- 但是它的拷贝操作会改变资源的所有权,导致使用了源对象变得无效,所以C++11后不建议使用auto_ptr,使用unique_ptr替代!
- unique_ptr 和 auto_ptr用法几乎一样,也是一种独占式智能指针,只不过更严谨一些。我看过它的源码,它是直接把自己的拷贝构造函数和拷贝赋值运算符给delete禁用掉了,只能进行移动操作,也就直接禁止两个指针指向同一个资源,提高了代码的严谨性和安全性。
unique_ptr(const unique_ptr& sp) = delete;不能通过拷贝构造函数来创建一个新的std::unique_ptr对象,即不允许复制另一个std::unique_ptr对象的资源所有权
unique_ptr& operator=(const unique_ptr& sp) = delete;这意味着你不能通过拷贝赋值运算符将一个std::unique_ptr对象赋值给另一个std::unique_ptr对象
- auto_ptr和unique_ptr中有个问题就是它们都具有排他性,也就是都不支持多个智能指针指向同一块资源,比较局限。而shared_ptr就是为了解决这个问题,shared_ptr会允许多个智能指针指向同一块资源,并且能够保证共享的资源只会被释放一次。
shared_ptr采用的是引用计数原理来实现多个shared_ptr对象之间共享资源:
shared_ptr会维护一份引用计数,用来记录当前资源被几个对象共享。
当拷贝的时候,引用计数加+1,当一个shared_ptr对象被销毁的时候,会调用析构函数把这个计数-1。
当计数为零的时候,代表已经没有指针指向这块内存,那么我们就释放它。
- 循环引用问题
- 循环引用是指使用多个智能指针share_ptr时,出现了指针之间相互指向,从而形成环,有点类似于死锁的情况。假设我们定义一个双向链表,把链表上节点都定义成shared_ptr智能指针,当其中两个节点互相引用的时候,就会出现循环引用的现象。
- std::shared_ptr 是线程安全的,在多线程情况下它的引用计数是通过原子操作来进行增减的
我们创建了两个节点A和B,初始引用都是1。让A的next指向B,B的pre指向A,引用变成2.
想要释放A空间必须让引用计数等于0,也就是必须先析构B空间的_pre
那就要求B空间的引用计数为0,前提是析构A空间的_next。
这样A等着B,B等着A形成了死锁,后果是析构函数无法调用,出现内存泄漏(虽然可以正常退出程序)
weak_ptr也叫弱引用,引入weak_ptr的初衷就是为了解决刚才说的shared_ptr可能出现的循环引用问题,它只能从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会影响到引用数。它可以观察到 std::shared_ptr 所管理对象的生命周期,但是并不会控制对象的生命周期。
存放局部变量和函数参数的地方,它是一块连续的内存区域由系统自动分配,函数执行结束时这些空间由系统自动释放。栈内存分配的计算优点是效率很高,有寄存器的支持,但是缺点是分配的内存容量有限(MB级别)
堆是我们通过new关键字来动态申请的内存空间,堆上分配的内存需要我们手动管理,堆是不连续的内存区域,以链表的形式分配的,如果我们没有正确释放堆上的内存可能会出现内存泄漏。
通常用来存储全局变量和静态变量,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始为0
通常用于存储常量数据,这部分内存是只读的
存放函数体的二进制代码,包括静态函数。通常代码区是可以共享的,因为对于频繁被执行的程序,只需要在内存中有一份代码就行了。
C++中类的数据成员和成员函数内存分布情况
虚函数表是用于实现C++多态性的关键机制之一。它用于存储类中每个虚函数的地址,类的每个实例化对象都有一个指向本类虚表的指针,在构造函数执行时会对虚表指针进行初始化。
当类被继承时,子类会继承父类的虚函数表。
当子类对父类的虚函数没有重写时,子类的虚表指针指向的是父类的虚表;当子类对父类的虚函数重写时,子类的虚表指针指向的是自身的虚表;
STL标准模板库,是 C++ 标准库的重要组成部分,包含了许多常用的数据结构和算法的软件框架。
STL提供了六大组件,彼此之间可以组合套用,这六大组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。
默认情况下,stack和queue使用 deque 作为其底层容器
deque是一种双向开口的连续线性空间。头尾两端都可以元素插入和删除,中间插入元素比较费时,因为必须移动中间其他的元素。
连续分段空间,由一段一段的连续空间构成的,用一小块连续的内存空间map作为主控(不是STL的map容器),里面的每一个元素都是一个指针,指向另一段连续性内存空间,称作缓冲区,默认使用 512 字节大小。Deque最大的工作就是维护这些分段连续的内存空间的整体性的假象。
默认情况下,stack和queue使用 deque 作为其底层容器
智能指针
NULL和nullptr
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。