admin管理员组文章数量:1608632
C++面试题汇总
- 1. C基础
-
- 1.1 内存模型
-
- 1.1.0 内存四区
- 1.1.1 简述C、C++程序编译的内存分配情况
- 1.1.2 分配函数与释放函数
-
- 1.1.2.1 malloc / free
- 1.1.2.2 new / delete
- 1.1.2.3 new/delete 与 malloc/free 区别
- 1.1.2.5 calloc 、realloc
- 1.1.2.6 在C++中,使用malloc申请的内存能否通过delete释放?使用new申请的内存能否用free?
- 1.2 预编译
-
- 1.2.1 头文件问题
- 1.2.2 const 与 #define相比有什么优点
- 1.3 宏,内联函数
-
- 1.3.1 内联函数
- 1.3.2 内联函数与宏的差别
- 1.3.3 写一个 “标准”宏MIN
- 1.3.4 typedef 和define 有什么区别
- 1.4 指针
-
- 1.4.1 指针常量和常量指针
- 1.4.2 指针函数和函数指针
- 1.4.3 指针数组数组指针
- 1.4.4 函数传参
- 1.4.5 一些定义
- 1.4.6 指针与引用的区别
- 1.4.7 this指针
- 1.4.8 指针和句柄
- 1.4.9 如何避免“野指针”
- 1.4.10 空指针与迷途指针区别
- 1.5 const
-
- 1.5.1 const 使用
- 1.5.2 const 作用
- 1.5.3 如何修改const成员函数
- 1.5.4 将Const类型转化为非Const类型
- 1.6 sizeof
-
- 1.6.1 sizeof 和strlen 的区别
- 1.6.2 sizeof 的使用场合
- 1.7 强制类型转换运算符
- 1.8 什么是右值引用,跟左值又有什么区别?
-
- 1.9 变量的声明和定义有什么区别
- 1.10 说一说extern“C”
- 2. C++面向对象
-
- 2.1 面对对象的三大特性(基本特征)
- 2.2 封装
- 2.3 继承
- 2.4 多态
- 2.5 成员函数
-
- 2.5.1 构造函数与析构函数
- 2.5.2 初始化列表方式
- 2.5.3 构造函数调用方式
- 2.5.4 C++的空类默认产生哪些成员函数
- 2.5.5 继承中子类和父类的构造和析构顺序
- 2.5.6 深拷贝与浅拷贝
- 2.5.6 拷贝构造函数与赋值运算符
- 2.5.7 C 语言的关键字 static 和 C++ 的关键字 static 有什么区别
- 2.5.8 静态成员
- 2.5.9 常函数与常对象
- 2.6 引用
-
- 2.6.1 引用
- 2.6.2 常引用
- 2.6.3 引用与指针区别
- 2.7 虚函数
-
- 2.7.1 虚函数与纯虚函数
- 2.7.2 抽象类
- 2.7.3 虚析构与纯虚析构
- 2.7.4 多态类中的虚函数表是compile-Time建立的还是Run-Time建立的
- 2.7.5 析构函数可为virtual型,构造函数不能,为什么?
- 2.7.6 能否把每个函数都声明为虚函数?
- 2.8 隐藏、重载与重写
- 2.9 class 与struct 区别
- 2.10 友元
- 3. STL
-
- 3.1 vector的底层原理
- 3.2 vector中的reserve和resize的区别
- 3.3 vector中的size和capacity的区别
- 3.4 vector中erase方法与algorithn中的remove方法区别
- 3.5 vector迭代器失效的情况
- 3.6 正确释放vector的内存(clear(), swap(), shrink_to_fit())
- 3.7 list的底层原理
- 3.8 什么情况下用vector,什么情况下用list,什么情况下用deque
- 3.9 priority_queue的底层原理
- 3.10 map 、set、multiset、multimap的底层原理
- 3.11 为何map和set的插入删除效率比其他序列容器高
- 3.12 为何map和set每次Insert之后,以前保存的iterator不会失效?
- 3.13 当数据元素增多时(从10000到20000),map的set的查找速度会怎样变化?
- 3.14 map 、set、multiset、multimap的特点
- 3.15 为何map和set的插入删除效率比其他序列容器高,而且每次insert之后,以前保存的iterator不会失效?
- 3.16 为何map和set不能像vector一样有个reserve函数来预分配数据?
- 3.17 set的底层实现实现为什么不用哈希表而使用红黑树?
- 3.18 hash_map与map的区别?什么时候用hash_map,什么时候用map?
- 3.19 迭代器失效的问题
- 3.20 STL线程不安全的情况
- 4. C++ 11
-
- 4.1 NULL与nullptr
-
- 4.1.1 C语言中的NULL
- 4.1.2 C++中的NULL
- 4.1.3 C++中的nullptr
- 4.2 智能指针
C++知识点总结: 快速跳转
1. C基础
1.1 内存模型
1.1.0 内存四区
意义在于:赋予其不同的生命周期,给编程带来更大的灵活性
- 运行前
- 代码区:存放函数体的二进制代码,由操作系统管理
- 共享的
- 只读的:防止程序意外修改其指令
- 全局区:存放全局变量和静态变量以及常量,结束后由系统释放
- 全局区还包括常量区(字符串常量,const修饰的全局常量)
- 代码区:存放函数体的二进制代码,由操作系统管理
- 运行后
- 栈区:由编译器自动分配和释放,存放函数体的参数值、局部变量等
- 不能返回局部变量的地址,当离开作用域后,开辟在栈区的局部变量会被编译器自动回收
- 堆区:由程序员分配和释放,若不释放,程序结束后由操作系统释放
- 分全局堆和局部堆
- 全局堆就是所有没有分配的空间,局部堆就是用户分配的空间
- 堆在操作系统对进程 初始化的时候分配,运行过程中也可以向系统要额外的堆
- 栈区:由编译器自动分配和释放,存放函数体的参数值、局部变量等
1.1.1 简述C、C++程序编译的内存分配情况
- 从静态存储区域分配:
内存在程序 编译 时 就已 经 分配 好,这块内 存在 程序 的整 个运行 期间 都存在 。速 度快、不容易出错 , 因 为 有系 统 会善 后。例 如全 局变 量, sta tic 变量, 常量 字符 串等。 - 在栈上分配:
在执行函数时, 函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。 栈内存分配运算内置于处理器的指令集中, 效率很高, 但是 分配的内存容量有限 。大小为2M。 - 从堆上分配:
即动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在何时用 free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏 ,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块 。
一个C、C++ 程序****编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码区 。
1.1.2 分配函数与释放函数
C:malloc、calloc、realloc / free
C++:new / delete
1.1.2.1 malloc / free
大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息——分配块的长度,指向下一个分配块的指针等等
- malloc函数向内存申请一块连续可用的空间
- 开辟成功则返回一个指向该空间的void* 型指针,所以需要对其进行强制类型转换,转换成我们想要的类型
- 开辟失败则返回 NULL,所以一定要对malloc的返回值进行检查
- free 用来释放动态开辟的内存,而不是释放指针
int* ptr = NULL;
ptr = (int*)malloc(1000*sizeof(int));//开辟一千个int大小的内存,并强制类型转换
if(NULL == ptr){
exit(1);
}
free(ptr);
ptr = NULL;
- 释放只能一次,如果释放两次及两次以上会出现错误
- 释放空指针例外,释放空指针其实也等于什么都没做,所以释放空指针释放多少次都没有问题
1.1.2.2 new / delete
new分配内存步骤
- 调用operator new 函数
- 调用相应的构造函数构造对象,并传入初值
- 对象构造完成后,返回一个指向该对象的指针
delete释放内存步骤
- 调用对象的析构函数
- 调用operator delete 函数释放内存空间
//开辟变量
int* a = new int(10);
delete a;
//开辟数组
int* arr = new int[10];
delete[] arr;
1.1.2.3 new/delete 与 malloc/free 区别
- 开辟位置
- 严格来说,malloc动态开辟的内存在堆区,new开辟的叫做自用存储区
- 若不重载new操作符,c++编译器一般默认使用堆来实现自用存储,此时等价于堆区
- 特别:new可以不为对象分配内存
- 重载
- new 、delete 是操作符,可以重载,只能在C++ 中使用。 malloc、free 是函数,可以覆盖,C、C++ 中都可以使用。
- 是否调用构造与析构函数
- new 可以调用对象的构造函数,对应的delete 调用相应的析构函数。malloc 仅仅分配内存,free 仅仅回收内存,并不执行构造和析构函数
- 是否需要指定内存大小
- malloc 需要显式指出开辟内存的大小,new 无需指定,编译器会自动计算
- 返回值类型
- new返回的是某种数据类型指针,malloc返回的是void 指针,new比malloc更安全
- new内存分配失败时,会抛出bac_alloc异常,不会返回NULL;malloc开辟内存失败会返回NULL指针,所以需要判断
1.1.2.5 calloc 、realloc
calloc(number,size):为number个大小为size的元素开辟一块空间,并把每个字节初始化为0
realloc(内存地址,大小):用于调整申请的空间大小
1.1.2.6 在C++中,使用malloc申请的内存能否通过delete释放?使用new申请的内存能否用free?
不能,malloc/free主要为了兼容C,new和 delete 完全可以取代malloc/free的。malloc/free 的操作对象都是必须明确大小的。而且不能用在动态类上。new 和 delete会自动进行类型检查和大小 ,malloc/free不能执行构造函数与析构函数 ,所 以动态对象它是不行的。当然从理论上说使用malloc 申请的内存是可以通过delete释放的 。不过一般不这样写的。而且也不能保证每个C++的运行时都能正常
1.2 预编译
1.2.1 头文件问题
- #include < >:只搜索系统目录,不会搜索本地目录
- #include " ":首先搜索本地目录,若找不到才会搜索系统目录
- #include<>相较于#include" " 快一些
1.2.2 const 与 #define相比有什么优点
- const 常量有数据类型,而宏常量没有数据类型,编译器可以对前者进行安全检查。对后者只进行字符替换,没有安全类型检查,并且在字符替换可能会产生意想不到的错误
- 有些集成化的调试工具可用对const进行调试,但是不能对宏常量进行调试
1.3 宏,内联函数
1.3.1 内联函数
- 定义:在函数定义体前加入关键字inline,使函数成为内联函数
- 增加空间消耗换取效率提高,这点与宏一样
- 内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用
void fun(int x,int y);
inline void fun(int x,int y){
//必须放在定义体前面,不能放在声明前面
...
}
- 适用情况
- 一个函数不断被重复调用
- 函数只有简单几行,且函数内不包括for、while、switch语句
1.3.2 内联函数与宏的差别
- 内联函数要做类型检查,而宏不需要
- 宏是在代码处不加任何验证的简单替代,而内联函数是将代码直接插入到调用处,而减少了普通函数调用时的资源消耗
1.3.3 写一个 “标准”宏MIN
#define min( a, b)( (a )<=(b) ?( a) :(b ))
1.3.4 typedef 和define 有什么区别
- 用法不同:typedef 用来定义一种数据类型的别名,增强程序的可读性。define 主要用来定义 常量,以及书写复杂使用频繁的宏。
- 执行时间不同:typedef 是编译过程的一部分,有类型检查的功能。define 是宏定义,是预编译的部分,其发生在编译之前,只是简单的进行字符串的替换,不进行类型的检查。
- 作用域不同:typedef 有作用域限定。define 不受作用域约束,只要是在define 声明后的引用 都是正确的。
- 对指针的操作不同:typedef 和define 定义的指针时有很大的区别。
注意:typed
版权声明:本文标题:C++面试题总结,一篇就够了 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728552466a1163503.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论