参考:
作者:小王同学在积累 链接:https://www.zhihu.com/question/440248845/answer/1698042313
作者:二进制架构 链接:https://www.zhihu.com/people/binarch/posts?page=2
1. 面向对象
struct和class有什么区别
在C++中,struct和class的唯一区别是默认的访问控制。
struct
默认的成员是public
的,而class
的默认成员是private
的
1.1 封装
C++面向对象的三大特性为:封装、继承、多态
。C++认为万事万物都皆为对象,对象上有其属性和行为
什么是封装
-
将属性和行为作为一个整体
,表现生活中的事物。将属性和行为加以权限控制 -
封装意义:
- 在设计类的时候,属性和行为写在一起,表现事物。
- 类在设计时,可以把属性和行为放在
不同的权限下
,加以控制。 - 访问权限有三种:public 公共权限;protected 保护权限;private 私有权限
1.2 继承
什么是继承?
有些类与类之间存在特殊的关系,比如动物类和猫类。我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。这个时候我们就可以考虑利用继承的技术,减少重复代码
1.3 多态
1.3.1 什么是多态?
多态分为两类
:
- 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
- 动态多态: 派生类和虚函数实现运行时多态
静态多态和动态多态区别:
- 静态多态的函数地址早绑定 - 编译阶段确定函数地址
- 动态多态的函数地址晚绑定 - 运行阶段确定函数地址
多态需满足的条件:
- 有继承关系,子类重写父类中的虚函数
- 多态使用条件:父类指针或引用指向子类对象
1.3.2 虚函数作用和意义
虚函数:虚函数是用于支持动态多态性的一种机制。如果一个类中声明了虚函数,那么在派生类中可以覆盖这个函数。在运行时,调用对象的虚函数会根据对象的实际类型来决定调用哪个函数。
1.3.3 什么是纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
- 纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ;
-
当类中有了纯虚函数,这个类也称为抽象类
。 - 抽象类特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
2. STL
2.1 什么是STL 其创建目的是什么
软件界一直希望建立一种
可重复利用
的东西。C++的面向对象
和泛型编程
思想,目的就是复用性
的提升。大多数情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作。为了建立数据结构和算法的一套标准,诞生了STL
。
2.2 STL的基本概念以及组成
STL(
Standard Template Library
,标准模板库)。STL几乎所有的代码都采用了模板类或者模板函数。
STL大体分为六大组件,分别是:容器
、算法
、迭代器
、仿函数
、适配器
(配接器)、分配器
。
2.3 请简单介绍STL的六大组件
- 容器:各种数据结构,如
vector、list、deque、set、map
等,用来存放数据。 - 算法:各种常用的算法,如sort、find、copy、for_each等。
- 迭代器:扮演了容器与算法之间的胶合剂。可以通过迭代器来遍历容器
- 仿函数:是一个可执行的对象,类型重载了operator()()运算符。
- 适配器:适配器是一种设计模式。主要起到将不同的接口统一起来的作用。STL中的容器适配器如stack和queue,通过调用容器的接口,实现适配器所需的功能。
- 分配器:主要用于内存的分配与释放。一般容器都会自带默认分配器,很少会自己实现分配器。
2.4 什么是STL容器,常用的容器有哪些
容器:存放数据的地方。STL容器就是将运用最广泛的一些数据结构实现出来。常用的数据结构:
数组
、链表
、树
、栈
、队列
、集合
、映射表
等
2.4 请简单介绍vector容器,其底层是怎么实现的
-
vector数据结构和数组非常相似,也称为单端数组。vector与普通数组区别:不同之处在于数组是静态空间,而
vector可以动态扩展
。 -
vector底层使用动态数组来存储元素对象,同时使用size和capacity记录当前元素的数量和当前动态数组的容量。如果持续的push_back(emplace_back)元素,
当size大于capacity时,需要开辟一块更大的动态数组,并把旧动态数组上的元素搬移到当前动态数组,然后销毁旧的动态数组。
2.5 push_back做了哪些操作,复杂度如何
push_back()用于在vector的末尾添加一个元素。如果当前的容量不足以容纳新的元素,那么vector的容量将会翻倍(
1.5~2倍
),这需要分配新的内存空间并将现有元素复制到新的位置,这是一个O(n)的操作。但是,如果考虑到每个元素平均被复制的次数,push_back()的平摊时间复杂度是O(1)。
2.6 有没有什么好的办法提升vector连续插入效率
如果知道数据的大概量,我们可以使用
reserve
方法直接为vector扩容这个量级。这样在后续的数据插入时就不会因为频繁的capacity被用尽而导致的多次的数据搬移
,从而提升vector插入效率
2.7 push_back和emplace_back有什么区别
为什么emplace_back效率更高?
push_back()会创建一个新的对象然后复制到vector中,而emplace_back()则是在vector中直接构造对象,
这可以避免不必要的复制或移动操作
。
2.8 请简单介绍一些set和map
- std::set是一个有序的集合,其中的元素是唯一的,即每个元素只能出现一次。一般用于去重和自动排序。
- std::map同样是有序组合,只不过它不止有key,每个key还对用一个value。其中key是唯一,不可重复,但是value却没有限制。key/value也被称为键值对
他们底层使用什么数据结构存储数据的吗?
两者都是使用
红黑树
作为底层的数据结构。红黑树是一种自动平衡的二叉树,它确保插入、删除和查找操作的时间复杂度都是O(log n)。是高效的查找树
2.9 map[key]和map.at(key)的区别
当map中不存在某个key时,map[key]操作会在map中增加一个键值对,键名为key,值是传入的value类型的默认值。而map.at(key)会报错,查找时更安全。
2.10 查询而言,是vector快还是map快
vector
的查询的时间复杂度是O(n)
,而map
是O(logn)
。如果在数据集很大的时候,当然是map快一些。但当数据量没那么大的时候
(少于1000条记录),vector要比map查询速度快。原因我们在之前的面试文章中讲过,vector内存连续,缓存更友好。map底层是红黑树,内存并不连续
。
3.指针
- 什么是指针
指针的作用:可以通过指针间接访问内存。
内存编号是从0开始记录的,一般用十六进制数字表示。
可以利用指针变量保存地址。
3.1 指针所占内存空间
- 在32位操作系统下,不管什么类型的指针都占
4个字节
的内存。 - 在64位操作系统下,不管什么类型的指针都占8个字节的内存,但是实际开发环境一般都是32位操作系统
3.2 什么是空指针和野指针
-
空指针
:指针变量指向内存中编号为0的空间(0,NULL,nullptr)。用途:初始化指针变量
。空指针指向的内存是不可以访问的。 -
野指针
:指针变量指向非法
的内存空间。野就是状态未知
的。它可能指向一块未知的区域:
0/NULL/nullptr
三者之间的区别?
虽然三者都能定义空指针,但三者类型不同。0是int类型,NULL在g++下是一个宏定义,而nullptr是有类型的;建议使用nullptr
定义空指针,因为它时有类型的,编译器能够对它进行类型检查。
3.3 如何解决空指针、野指针带来的问题
- 在解引用指针之前,要判断指针是否为空。(解决空指针解引用问题)
- 对于定义的指针,一定要进行初始化(=nullptr)。(解决野指针问题)
- 对于释放过内容的指针,立即将指针置为nullptr。(解决垂悬指针、指针二次释放问题)
- 要注意长生命周期的指针不能指向短生命周期的对象。(解决垂悬指针问题)
- C++11之后使用智能指针
3.4 什么是智能指针?有哪些智能指针?
智能指针是C++11引入的类模板,用于管理资源,行为类似于指针,但不需要手动申请、释放资源
,所以称为智能指针。有三种智能指针,分别是shared_ptr
、unique_ptr
、和weak_ptr
。
3.5 这三种智能指针有什么不同和用途
-
shared_ptr
使用了引用计数
(use count)技术,当复制个shared_ptr对象时,被管理的资源并没有被复制,而是增加了引用计数。当析构一个shared_ptr对象时,也不会直接释放被管理的的资源,而是将引用计数减一。当引用计数为0时,才会真正的释放资源。shared_ptr可以方便的共享资源而不必创建多个资源。 -
unique_ptr
则不同。unique_ptr独占资源,不能拷贝,只能移动。移动过后的unique_ptr实例不再占有资源。当unique_ptr被析构时,会释放所持有的资源。 -
weak_ptr
可以解决shared_ptr所持有的资源循环引用问题。weak_ptr在指向shared_ptr时,并不会增加shared_ptr的引用计数。所以weak_ptr并不知道shared_ptr所持有的资源是否已经被释放。这就要求在使用weak_ptr获取shared_ptr时需要判断shared_ptr是否有效。
4 static和const
4.1 static和const的关键用法
-
satic关键字主要用在以下三个方面:
- 1.用在全局作用域,修饰的变量或者函数为静态的,限制在本文件内使用。
- 2.方法内修饰修饰静态局部变量,在第一次访问的时候初始化。只能在本文件内使用。
- 3.内类修饰成员函数和成员变量,此函数或变量由类持有,而非类的对象持有。
-
const关键字主要也有三个用途:文章来源:https://www.toymoban.com/news/detail-832969.html
- 1.修饰函数参数,则在函数内部不可以修改此参数。
- 2.修饰类的成员方法,表面此方法不会更改类对象的任何数据。
- 3.修饰变量,表明变量不可以被修该。
4.2 const int* 和int * const的区别
这要要看const和* 的位置,const在前称为常量指针,const在后称为指针常量。常量指针的指针的指向可变,指针指向的内容不可变。指针常量则相反,指针指向的内容可变,指针的指向不可变文章来源地址https://www.toymoban.com/news/detail-832969.html
到了这里,关于C++面试高频问题汇总( 一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!