c++ 面试常见问答

一、指针和引用的区别

  1. 本质:指针是一个实体,需要分配内存空间,引用只是变量的别名,不需要分配内存空间
  2. 内存分配:指针与引用都需要分配内存区域,引用在定义的时候必须初始化,一旦引用与某个变量绑定后就不再改变
  3. 级数:有多级指针,没有多级引用
  4. 自增含义:指针自增代表指向下一个空间,引用自增代表引用的变量值加1
  5. sizeof 大小:sizeof引用得到的是指向变量的大小,sizeof 指针得到的是指针本身的大小
  6. 访问方式:引用访问一个变量是直接访问,指针访问一个变量是间接访问
  7. 安全检查:使用指针前最好做类型检查,防止野指针的出现,引用可以防止野指针的出现
  8. 引用底层是通过指针实现的
  9. 作为参数时的不同:传指针的实质是传值,传递的值是指针的地址,传引用的实质是传地址,传递的是变量的地址

二、static 关键字的用法和作用

  • 告知编译器讲变量存放在程序的静态存储区而非 栈上/堆上 空间(编译时初始化)
  • 同时编译多个文件时,所有未加static前缀的全局变量都有全局可见性,即a.cpp可以使用extern 调用b.cpp里面的全局变量;若加了static 修饰,则该全局变量只对该文件有效,可以解决命名冲突的问题
  • 优势:可以节省内存,因为它是所有对象所公有的
  • 注意:
    1. 函数体内的static 变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次
    2. 模块内的static 变量可以被模块内的所有函数访问,但不能被其他模块使用
    3. static 类成员函数不能访问非 static 成员变量 ---> static 函数内没有this 指针,无法访问私有变量

三、const 关键字

  • 阻止一个变量被修改

  • 函数声明内可以使用const 修饰形参,表明其是一个输入参数,在函数内部不可以改变其值

  • const 的几种用法:

    1. const int *p ---- 常量指针,不可以通过这个指针改变其所指向的变量的值
    2. int * const p ---- 指针常量,p的值不可变
    3. const int* const p ---- 指向常量的常指针

四、虚函数、内联函数

  1. 虚函数用于实现运行时的多态,实现方式:C++ 内存模型规定最开始的四个字节(32位机器)为指向虚函数表的指针(vptr), 当把子类的实例赋值给基类指针,基类的vptr就会指向子类的虚函数表

  2. 内联函数在编译时将所有运用内联函数的地方替换为代码块

五、构造函数不可以为虚函数,析构函数需要为虚函数

  • 虚函数表是在构造函数内初始化的,构造函数设置为虚函数,会导致对应类无法初始化一个对象
  • 析构函数如果不设置为虚函数,则在多态情况下,析构基类的同时,无法析构基类指向的子类

六、容器内部元素的删除

  1. 顺序容器
    • erase 迭代器不仅使所指向被删除的迭代器失效,而且使被删元素之后的所有迭代器失效,不可以使用erase(it++) 的方式,但是 erase(it)的返回值是下一个迭代器,it=erase(it)
  2. 关联容器
    • erase 迭代器只是使得被删除元素的迭代器失效,返回值为void, 采用 erase(it++)的形式删除迭代器

七、c++ 对struct进行了进一步的扩展,使struct在c++中可以和class一样当作类使用,唯一与class不同的地方在于struct 的成员默认访问权限是public, class 是private

八、c/c++ 内存分配

  1. 栈区:由编译器自动分配释放,存放函数的参数值,局部变量的值,其操作方式类似于数据结构中的栈
  2. 堆区:由程序员分配释放,若程序员不释放,程序结束时由os回收(比较危险,程序员自己不回收容易引起内存泄漏)
  3. 全局区(静态区):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量,在相邻的另一块区域
  4. 文字常量区:常量字符串就是放置在这里的,程序结束后由系统释放
  5. 程序代码区:存放程序的二进制代码

九、野指针和内存泄漏

  1. 野指针:指向被释放的内存或者没有访问权限的内存
  2. 内存泄漏:由于程序员的疏忽或错误导致程序未能释放掉不再使用的内存的情况,解决办法:智能指针

十、new 和 malloc 区别

  1. new 运算符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,malloc 需要显示给出所需内存的大小
  2. new 操作符分配成功时,返回对象类型的指针,malloc内存分配成功,则返回void *,必须要通过强转变成所需要的类型

十一、空类的大小

  • 空类的大小是1,c++ 要求对于每个类的实例都要有独一无二的地址,编译器会自动为空类分配一个字节大小,这样子保证了每个实例均有独一无二的地址
  • 带虚函数的c++ 空类大小不为1,因为有vptr的存在

十二、虚函数的代价

  1. 带有虚函数的类,每一个虚函数类会产生一个虚函数表,用来存放指向虚成员函数的指针,从而增加类的大小
  2. 带有虚函数的类的每一个对象,都会有一个指向虚表的指针,会增加对象的占用空间大小
  3. 虚函数不可以作为内联函数

十三、c++ 类型转换

  1. static_cast ----- 一般的转换
  2. dynamic_cast ----- 通常用于基类派生类之间的转换
  3. const_cast ----- 主要用于针对const的转换
  4. reinterpret_cast ----- 用于没有任何关联的转换,比如一个字符指针转换为一个整数

十四、空类有哪些默认的函数

  1. 缺省构造函数
  2. 拷贝构造函数
  3. 析构函数
  4. operator= 赋值运算符重载函数
  5. 取地址运算符重载函数

十五、代码段从0地址开始的吗
否,0地址开始处的空间是不被使用的(逻辑地址)

十六、c++11 新特性

  1. 右值引用
  2. 初始化列表
  3. 类型推导
  4. 基于范围的for循环
  5. lamda 表达式
  6. 空指针 nullptr
  7. 智能指针
  8. 正则表达式

十七、迭代器失效的几种情况

  1. 对于序列式容器,删除当前的iterator,会使得后面所有元素的迭代器失效
  2. 使用pushback后,导致vector扩容,进而导致迭代器失效
  3. list中,元素的删除操作会导致指向该元素的迭代器失效

十八、模板函数不可以是虚函数
模板函数需要根据调用情况生成不同的实例,虚函数表的大小却需要在编译时确定

十九、虚函数可以定义为static吗?
不可以,虚函数是通过this指针调用的,而static函数内部没有this指针

二十、静态库与动态库区别
静态库在编译时就被载入可执行程序,体积较大,动态库在编译时加入标记,在运行时才加载动态库,体积较小,而且可以提高代码的可复用度

二十一、一个进程可以创建多少线程,和什么有关
一个进程可以创建的线程数由可用虚拟空间和线程的栈大小共同决定
只要虚拟空间足够,那么新线程的创建就会成功

二十二、线程间什么是共享的,什么是不共享的
堆,全局变量,静态变量是共享的
栈与寄存器不是共享的

二十三、线程间通信机制

  1. 锁机制
  2. 信号量机制
  3. 信号机制
  4. volatile 全局变量

二十四、实例化一个对象要经过哪几个阶段

  1. 分配空间:对于全局对象,静态对象,以及分配在栈区域的对象,他们的内存分配在编译时已经确定了,堆上的对象,它们的内存分配是在运行时动态进行的
  2. 初始化虚函数表,虚函数指针
  3. 赋值,执行构造函数体

二十五、const和宏定义的区别

  1. 类型与安全检查不同,宏定义是字符串替换,const是常量的声明,需要在编译时进行类型检查
  2. 存储方式不同:宏定义是直接替换,不分配内存,存储在程序的代码段内;const常量需要进行内存分配,存储在数据段
  3. 定义域不同,宏定义不受定义域限制,const定义域为该函数体
  4. define 定义后可以通过 undef 取消,const常量定义后在定义域内永远有效

二十六、std::move
将左值转化为右值,右值仍为右值,常配合 std::forward使用实现完美转发
实现:

template <class T>
typename tinySTL::remove_reference<T>::type&& move(T&& t) noexcept {
    using return_type = typename tinySTL::remove_reference<T>::type&&;
    return static_cast<return_type>(t);
}

如果一个函数模板参数类型为T&&,其中T是需要推到的类型,那么T&&表示万能引用。
万能引用实际用到的技术是引用折叠。
引用折叠的规则可以概括为:
X& &、X& && 和 X&& & 折叠成 X&;
X&& && 折叠成 X&&。
如果T = X&是左值引用,则展开后得到了X& &&,根据上面的规则,最终得到X&。
如果T = X&&是右值引用,则展开后得到了X& &&,根据上面的规则,最终得到X&&。
所以,当t为左值或者左值引用时,进过引用折叠,得到的类型是T&。最后就是将左值转换为右值并返回了。

#蔚来面试##字节面试##阿里面试##华为面试#
全部评论
顶顶顶顶
点赞 回复 分享
发布于 2022-06-18 01:00
点赞 回复 分享
发布于 2022-06-24 09:32
非常好我这几天面试中了好多
点赞 回复 分享
发布于 2022-06-28 22:53
不错哦
点赞 回复 分享
发布于 2022-07-03 15:37
点赞 回复 分享
发布于 2022-07-18 20:57
我顶顶顶
点赞 回复 分享
发布于 2022-07-19 17:29
点赞 回复 分享
发布于 2022-07-31 07:51
码住码住学习
点赞 回复 分享
发布于 2022-08-12 12:47
点赞 回复 分享
发布于 2022-08-14 19:03

相关推荐

数开面试题使用的hive,tez计算引擎1.如何建模、以及数据开发过程中需要注意的问题(数据探查、数据开发、数据质量监测、数据核对)2.页面数据有问题、如何排查3.抽数、推数数据量异常如何自动停止任务(要有工作日、非工作日的判断,非工作日不生效,UDF函数)4.hive表生命周期管理失效,如何进行生命周期管理(设成自动任务的话可能会使用shell脚本)(3个月前每月保留第一天与最后一天的数据,注意是业务时间第一天与最后一天,非调度时间)5.数据量大的表推数慢影响页面展示怎么解决6.根据2个日期计算工作日天数7.去重方式(开窗函数如何控制窗口的大小)8.列转行(清洗、分隔符统一、注意有些业务数据(比如一条数据楼栋面积字段(可能是总面积)对应多个房屋或多个楼栋)、LATERAL&nbsp;VIEW&nbsp;explode)9.明细表数据量大,每月还要都保留一份,怎处理?怎么优化?达梦分区(范围分区、哈希分区、列表分区、组合(多级)分区、间隔分区(属于范围分区)INTERVAL&nbsp;&amp;lt;间隔表达式&amp;gt;)10.更新数据效率更高的方式update采用的类似nested&nbsp;loop的方式,对更新的每一行,都会对查询的表扫描一次;merge&nbsp;into这里选择的是hash&nbsp;join,则针对每张表都是做了一次&nbsp;full&nbsp;table&nbsp;scan,对每张表都只是扫描一次。11、筛选的时候in(不适合B大)、exists不适合B大)、join的底层以及效率12.常用的分析函数13.连续3天及以上连续出现的次数(减序号) #实习#&nbsp;&nbsp;#校招#&nbsp;&nbsp;#大厂#&nbsp;&nbsp;#数开#&nbsp;&nbsp;#数仓#
查看13道真题和解析
点赞 评论 收藏
分享
11-06 18:30
已编辑
门头沟学院 Java
10.25一面,原定30min,实面18min,KPI面。没有收到后续1、自我介绍2、看项目中用到了rabbitmq,说下它的主要作用答了解耦、异步和削峰3、如果建立了联合索引(a,b,c)现在查询条件顺序是c,b,a会用到索引么4、对于两个字段的or查询,如何保证走索引,例如查询name=?or&nbsp;student_id=?没答出来,就说给两个字段都建索引呗,面试官表示好像不太行5、看你简历有用到分布式锁,用的哪种实现6、项目中写了es,数据是怎么导入es的回答分页查询,使用线程池导入...7、直接连接的数据库和es进行导入的?用的什么jar包连接的有点无语,jar包名字记不住...8、Spring&nbsp;Cloud用的是阿里的那套还是什么,用到哪些组件9、Gateway路由分发的策略10、微服务之间的调用是怎么实现的知道吗11、服务A调用服务B,会经过nacos么12、有用过别的组件么回答都写在简历上了,没用过别的反问:1、面试流程两轮技术+hr2、有什么要&nbsp;改进的地方,给些建议说招聘后端开发工程师看的是对这些技术的掌握程度,包括对技术选型上的一些思考,比如你项目中用到了rabbitmq,那思考过不同的消息队列之间的区别吗,比如说项目中用的是redisson实现的分布式锁,有没有考虑和其他实现方式的区别。(这里我非常不解,为什么他面试中不问我这些区别,点评却要说这些)。#顺丰##顺丰科技##一面##一面凉经##kpi面#
顺丰集团一面100人在聊 查看14道真题和解析
点赞 评论 收藏
分享
58 401 评论
分享
牛客网
牛客企业服务