持续更新 | C++面试高频问题汇总!

本文详细介绍了C++中的struct和class的区别、封装、继承、多态的概念,以及STL(标准模板库)的组成部分,包括容器、算法、指针和智能指针,以及vector、set和map等数据结构的特性和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者 | 求求你们别学了  编辑 | 汽车人

原文链接:https://zhuanlan.zhihu.com/p/644283667

点击下方卡片,关注“自动驾驶之心”公众号

ADAS巨卷干货,即可获取

点击进入→自动驾驶之心【求职交流】技术交流群

本文只做学术分享,如有侵权,联系删文

汇总:class、封装、继承、多态、STL、指针和智能指针、static和const、其他零碎知识

参考:
作者:小王同学在积累 链接:https://www.zhihu.com/question/440248845/answer/1698042313

作者:二进制架构 链接:https://www.zhihu.com/people/binarch/posts?page=2

class:面向对象

  • struct和class有什么区别?

在C++中,struct和class的唯一区别是默认的访问控制。struct默认的成员是public的,而class的默认成员是private的。

封装

C++面向对象的三大特性为:封装、继承、多态。C++认为万事万物都皆为对象,对象上有其属性和行为

  • 什么是封装?

属性和行为作为一个整体,表现生活中的事物。将属性和行为加以权限控制
封装意义
在设计类的时候,属性和行为写在一起,表现事物。
类在设计时,可以把属性和行为放在不同的权限下,加以控制。
访问权限有三种:public 公共权限;protected 保护权限;private 私有权限

继承

  • 什么是继承?

有些类与类之间存在特殊的关系,比如动物类和猫类。我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。这个时候我们就可以考虑利用继承的技术,减少重复代码

多态

  • 什么是多态?

多态分为两类:
静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
动态多态: 派生类和虚函数实现运行时多态
静态多态和动态多态区别:
静态多态的函数地址早绑定 - 编译阶段确定函数地址
动态多态的函数地址晚绑定 - 运行阶段确定函数地址
多态需满足的条件:有继承关系,子类重写父类中的虚函数
多态使用条件:父类指针或引用指向子类对象

  • 虚函数作用和意义?

虚函数:虚函数是用于支持动态多态性的一种机制。如果一个类中声明了虚函数,那么在派生类中可以覆盖这个函数。在运行时,调用对象的虚函数会根据对象的实际类型来决定调用哪个函数。

  • 什么是纯虚函数和抽象类?

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ;
当类中有了纯虚函数,这个类也称为抽象类。
抽象类特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类。

STL

  • 什么是STL?其创建目的是什么?

软件界一直希望建立一种可重复利用的东西。C++的面向对象和泛型编程思想,目的就是复用性的提升。大多数情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作。为了建立数据结构和算法的一套标准,诞生了STL。

  • STL的基本概念以及组成?

STL(Standard Template Library,标准模板库)。STL几乎所有的代码都采用了模板类或者模板函数。
STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、分配器。

  • 请简单介绍STL的六大组件。

  1. 容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。

  2. 算法:各种常用的算法,如sort、find、copy、for_each等。

  3. 迭代器:扮演了容器与算法之间的胶合剂。可以通过迭代器来遍历容器

  4. 仿函数:是一个可执行的对象,类型重载了operator()()运算符。

  5. 适配器:适配器是一种设计模式。主要起到将不同的接口统一起来的作用。STL中的容器适配器如stack和queue,通过调用容器的接口,实现适配器所需的功能。

  6. 分配器:主要用于内存的分配与释放。一般容器都会自带默认分配器,很少会自己实现分配器。

  • 什么是STL容器,常用的容器有哪些?

容器:存放数据的地方。STL容器就是将运用最广泛的一些数据结构实现出来。常用的数据结构:数组、链表、树、栈、队列、集合、映射表 等。

  • 请简单介绍vector容器,其底层是怎么实现的?

vector数据结构和数组非常相似,也称为单端数组。vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展。
vector底层使用动态数组来存储元素对象,同时使用size和capacity记录当前元素的数量和当前动态数组的容量。如果持续的push_back(emplace_back)元素,当size大于capacity时,需要开辟一块更大的动态数组,并把旧动态数组上的元素搬移到当前动态数组,然后销毁旧的动态数组。

  • push_back做了哪些操作,复杂度如何

push_back()用于在vector的末尾添加一个元素。如果当前的容量不足以容纳新的元素,那么vector的容量将会翻倍(1.5~2倍),这需要分配新的内存空间并将现有元素复制到新的位置,这是一个O(n)的操作。但是,如果考虑到每个元素平均被复制的次数,push_back()的平摊时间复杂度是O(1)。

  • 有没有什么好的办法提升vector连续插入效率?

如果知道数据的大概量,我们可以使用reserve方法直接为vector扩容这个量级。这样在后续的数据插入时就不会因为频繁的capacity被用尽而导致的多次的数据搬移,从而提升vector插入效率。

  • push_back和emplace_back有什么区别?为什么emplace_back效率更高?

push_back()会创建一个新的对象然后复制到vector中,而emplace_back()则是在vector中直接构造对象,这可以避免不必要的复制或移动操作。

  • 请简单介绍一些set和map

std::set是一个有序的集合,其中的元素是唯一的,即每个元素只能出现一次。一般用于去重和自动排序。
std::map同样是有序组合,只不过它不止有key,每个key还对用一个value。其中key是唯一,不可重复,但是value却没有限制。key/value也被称为键值对。

  • 他们底层使用什么数据结构存储数据的吗?

两者都是使用红黑树作为底层的数据结构。红黑树是一种自动平衡的二叉树,它确保插入、删除和查找操作的时间复杂度都是O(log n)。是高效的查找树

  • map[key]和map.at(key)的区别

当map中不存在某个key时,map[key]操作会在map中增加一个键值对,键名为key,值是传入的value类型的默认值。而map.at(key)会报错,查找时更安全。

  • 查询而言,是vector快还是map快?

vector的查询的时间复杂度是O(n),而map是O(logn)。如果在数据集很大的时候,当然是map快一些。但当数据量没那么大的时候(少于1000条记录),vector要比map查询速度快。原因我们在之前的面试文章中讲过,vector内存连续,缓存更友好。map底层是红黑树,内存并不连续。

指针

  • 什么是指针?

指针的作用:可以通过指针间接访问内存。

  1. 内存编号是从0开始记录的,一般用十六进制数字表示。

  2. 可以利用指针变量保存地址。

  • 指针所占内存空间?

在32位操作系统下,不管什么类型的指针都占4个字节的内存。
在64位操作系统下,不管什么类型的指针都占8个字节的内存,但是实际开发环境一般都是32位操作系统下。

  • 什么是空指针和野指针?

空指针:指针变量指向内存中编号为0的空间(0,NULL,nullptr)。用途:初始化指针变量。空指针指向的内存是不可以访问的。
野指针:指针变量指向非法的内存空间。野就是状态未知的。它可能指向一块未知的区域:0/NULL/nullptr三者之间的区别?
虽然三者都能定义空指针,但三者类型不同。0是int类型,NULL在g++下是一个宏定义,而nullptr是有类型的;建议使用nullptr定义空指针,因为它时有类型的,编译器能够对它进行类型检查。

  • 如何解决空指针、野指针带来的问题?

  1. 在解引用指针之前,要判断指针是否为空。(解决空指针解引用问题)

  2. 对于定义的指针,一定要进行初始化(=nullptr)。(解决野指针问题)

  3. 对于释放过内容的指针,立即将指针置为nullptr。(解决垂悬指针、指针二次释放问题)

  4. 要注意长生命周期的指针不能指向短生命周期的对象。(解决垂悬指针问题)

  5. C++11之后使用智能指针。

  • 什么是智能指针?有哪些智能指针?

智能指针是C++11引入的类模板,用于管理资源,行为类似于指针,但不需要手动申请、释放资源,所以称为智能指针。有三种智能指针,分别是shared_ptr、unique_ptr、和weak_ptr 。

  • 这三种智能指针有什么不同和用途?

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是否有效。

static和const

  • static和const的关键用法?

satic关键字主要用在以下三个方面:1.用在全局作用域,修饰的变量或者函数为静态的,限制在本文件内使用。2.方法内修饰修饰静态局部变量,在第一次访问的时候初始化。只能在本文件内使用。3.内类修饰成员函数和成员变量,此函数或变量由类持有,而非类的对象持有。
const关键字主要也有三个用途:1.修饰函数参数,则在函数内部不可以修改此参数。2.修饰类的成员方法,表面此方法不会更改类对象的任何数据。3.修饰变量,表明变量不可以被修该。

  • 现在两个指针,一个是 const int*,另一个是int * const,两者有什么区别?

这要要看const* 的位置,const在前称为常量指针,const在后称为指针常量。常量指针的指针的指向可变,指针指向的内容不可变。指针常量则相反,指针指向的内容可变,指针的指向不可变。

投稿作者为『自动驾驶之心知识星球』特邀嘉宾,欢迎加入交流!

① 全网独家视频课程

BEV感知、毫米波雷达视觉融合多传感器标定多传感器融合多模态3D目标检测车道线检测轨迹预测在线高精地图世界模型点云3D目标检测目标跟踪Occupancy、cuda与TensorRT模型部署大模型与自动驾驶Nerf语义分割自动驾驶仿真、传感器部署、决策规划、轨迹预测等多个方向学习视频(扫码即可学习

28496b12cd7ee83ecc0b1ee058d708b3.png 视频官网:www.zdjszx.com

② 国内首个自动驾驶学习社区

近2400人的交流社区,涉及30+自动驾驶技术栈学习路线,想要了解更多自动驾驶感知(2D检测、分割、2D/3D车道线、BEV感知、3D目标检测、Occupancy、多传感器融合、多传感器标定、目标跟踪、光流估计)、自动驾驶定位建图(SLAM、高精地图、局部在线地图)、自动驾驶规划控制/轨迹预测等领域技术方案、AI模型部署落地实战、行业动态、岗位发布,欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频,期待交流!

204dec9a256a4b041882958fc075fc94.png

③【自动驾驶之心】技术交流群

自动驾驶之心是首个自动驾驶开发者社区,聚焦目标检测、语义分割、全景分割、实例分割、关键点检测、车道线、目标跟踪、3D目标检测、BEV感知、多模态感知、Occupancy、多传感器融合、transformer、大模型、点云处理、端到端自动驾驶、SLAM、光流估计、深度估计、轨迹预测、高精地图、NeRF、规划控制、模型部署落地、自动驾驶仿真测试、产品经理、硬件配置、AI求职交流等方向。扫码添加汽车人助理微信邀请入群,备注:学校/公司+方向+昵称(快速入群方式)

0b31444509cd415a8e8735e046e08826.jpeg

④【自动驾驶之心】平台矩阵,欢迎联系我们!e651772477772d82f014e7daf0c5bece.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值