概述
C++八股总结——STL及类专题
- 一. 智能指针
- 1. 智能指针原理
- 2. 常用的智能指针
- (1)shared_ptr
- 实现原理
- (2)unique_ptr
- 实现原理
- (3)weak_ptr
- 实现原理
- (4)auto_ptr
- 应用场景
- 二. vector
- 1. 基本介绍
- 2. 时间复杂度
- 3. 与数组的区别
- 4. push_back()和emplace_back()的区别
- 二. list
- 1. 基本介绍
- 2. 时间复杂度
- 三. map、set、multimap、multiset
- 1. 基本介绍
- 2. 时间复杂度
- 四. unordered_map、unordered_set、unordered_multimap、 unordered_multiset
- 1. 基本介绍
- 2. 时间复杂度
- 五. 多态
- 1. 多态实现方式
- 2. 虚函数和纯虚函数
- (1)虚函数
- (2)纯虚函数
- 3. 虚函数表的原理和实现
- 4. 实现多态的过程
一. 智能指针
1. 智能指针原理
智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源。
2. 常用的智能指针
(1)shared_ptr
实现原理
实现原理:采用引用计数器的方法,允许多个智能指针指向同一个对象,每当多一个指针指向该对象时,指向该对象的所有智能指针内部的引用计数加1,每当减少一个智能指针指向对象时,引用计数会减1,当计数为0的时候会自动的释放动态分配的资源。
(2)unique_ptr
实现原理
unique_ptr采用的是独享资源所有权,一个非空的unique_ptr总是拥有它所指向的资源。转移一个unique_ptr将会把所有权全部从源指针转移给目标指针,源指针被置空;所以unique_ptr不支持普通的拷贝和赋值操作,不能用在STL标准容器中;局部变量的返回值除外(因为编译器知道要返回的对象将要被销毁);如果你拷贝一个unique_ptr,那么拷贝结束后,这两个unique_ptr都会指向相同的资源,造成在结束时对同一内存指针多次释放而导致程序崩溃。
(3)weak_ptr
实现原理
弱引用。 引用计数有一个问题就是互相引用形成环(环形引用),这样两个指针指向的内存都无法释放。需要使用weak_ptr打破环形引用。weak_ptr是一个弱引用,它是为了配合shared_ptr而引入的一种智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,也就是说,它只引用,不计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定是有效的,在使用之前使用函数lock()检查weak_ptr是否为空指针。
(4)auto_ptr
应用场景
主要是为了解决“有异常抛出时发生内存泄漏”的问题 。因为发生异常而无法正常释放内存。auto_ptr不支持拷贝和赋值操作,不能用在STL标准容器中。
二. vector
1. 基本介绍
vector和数组类似,拥有一段连续的内存空间,并且起始地址不变,在尾端增删元素具有较佳的性能。
2. 时间复杂度
随机访问复杂度:O(1);
插入: O(N)
查看: O(1)
删除: O(N)
3. 与数组的区别
vector不需程序员自己去考虑容量问题,库里面本身已经实现了容量的动态增长,而数组需要程序员手动写入扩容函数进形扩容。
4. push_back()和emplace_back()的区别
push_back()函数向容器中加入一个临时对象(右值元素)时,首先会调用构造函数生成这个对象,然后调用拷贝构造函数将这个对象放入容器中,最后释放临时对象。
emplace_back()函数向容器中加入临时对象,临时对象原地构造,没有拷贝或移动的操作,所以效率比较高。
二. list
1. 基本介绍
list是由双向链表实现的,元素存放在堆中, 因此内存空间是不连续的。只能通过指针访问数据。list是一个双链表结构,支持对链表的双向遍历。每个节点包括三个信息:元素本身,指向前一个元素的节点(prev)和指向下一个元素的节点(next)。因此list可以高效率的对数据元素任意位置进行访问和插入删除等操作。由于涉及对额外指针的维护,所以开销比较大。
2. 时间复杂度
随机访问复杂度:O(n);
插入: O(1)
查看: O(N)
删除: O(1)
三. map、set、multimap、multiset
1. 基本介绍
上述四种容器采用红黑树实现,红黑树是平衡二叉树的一种。
2. 时间复杂度
插入: O(logN)
查看: O(logN)
删除: O(logN)
四. unordered_map、unordered_set、unordered_multimap、 unordered_multiset
1. 基本介绍
上述四种容器采用哈希表实现
2. 时间复杂度
插入: O(1),最坏情况O(N)
查看: O(1),最坏情况O(N)
删除: O(1),最坏情况O(N)
五. 多态
1. 多态实现方式
在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据所指对象的实际类型来调用相应的函数,如果对象类型是派生类,就调用派生类的函数,如果对象类型是基类,就调用基类的函数。
2. 虚函数和纯虚函数
(1)虚函数
虚函数的主要作用是实现“运行时多态”, 父类中提供虚函数的实现,为子类提供默认的函数实现,子类可以重写父类的虚函数实现子类的特殊化。
(2)纯虚函数
C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new生成对象,只有实现了这个纯虚函数的子类才能new出对象。
3. 虚函数表的原理和实现
编译器在编译的时候,发现基类中有虚函数,此时编译器会为每个包含虚函数的类创建一个虚表(即vtable),该表是一个一维数组(而不是一个链表),在这个数组中存放每个虚函数的地址。如果基类和派生类都包含了一个虚函数func(),编译器会为这两个类都建立一个虚表。
4. 实现多态的过程
(1)编译器在发现基类中有虚函数时,会自动为每个含有虚函数的类生成一份虚表,该表是一个一维数组,虚表里保存了虚函数的入口地址。
(2)编译器会在每个对象的前四个字节中保存一个虚表指针,即vptr,指向对象所属类的虚表。在构造时,根据对象的类型去初始化虚指针vptr,从而让vptr指向正确的虚表,从而在调用虚函数时,能找到正确的函数。
(3)所谓的合适时机,在派生类定义对象时,程序运行会自动调用构造函数,在构造函数中创建虚表并对虚表初始化。在构造子类对象时,会先调用父类的构造函数,此时,编译器只“看到了”父类,并为父类对象初始化虚表指针,令它指向父类的虚表;当调用子类的构造函数时,为子类对象初始化虚表指针,令它指向子类的虚表。
(4)当派生类对基类的虚函数没有重写时,派生类的虚表指针指向的是基类的虚表;当派生类对基类的虚函数重写时,派生类的虚表指针指向的是自身的虚表;当派生类中有自己的虚函数时,在自己的虚表中将此虚函数地址添加在后面。
最后
以上就是明理羽毛为你收集整理的C++八股总结——STL及类专题一. 智能指针二. vector二. list三. map、set、multimap、multiset四. unordered_map、unordered_set、unordered_multimap、 unordered_multiset五. 多态的全部内容,希望文章能够帮你解决C++八股总结——STL及类专题一. 智能指针二. vector二. list三. map、set、multimap、multiset四. unordered_map、unordered_set、unordered_multimap、 unordered_multiset五. 多态所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复