C++八股总结——STL及类专题

一. 智能指针

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)当派生类对基类的虚函数没有重写时,派生类的虚表指针指向的是基类的虚表;当派生类对基类的虚函数重写时,派生类的虚表指针指向的是自身的虚表;当派生类中有自己的虚函数时,在自己的虚表中将此虚函数地址添加在后面。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值