🍓个人主页:个人主页
🍒系列专栏:C/C++基础与进阶
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习
VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931
1、C++面向对象的三大特性是什么?谈谈你对这三大特性的认识
封装,继承和多态,这是最基本最常见的面试题。
封装:隐藏了类的实现细节和成员数据,实现了代码模块化,如类里面的private和protect;
继承:使得子类可以复用父类的数据成员和方法,实现了代码重用;
多态:是一个接口多种实现状态。多态包括编译时多态和运行时多态,编译时多态(静态多态)主要包含函数重载与模板,运行时多态(动态多态)是由继承及虚函数实现的动态绑定。
2、#include <filename.h>和#include “filename.h”有什么区别?
这两种方式与编译器编译时搜索头文件的路径有关系。
对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h
对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h
3、C++程序内存的五大分区是哪五个?每个分区用来存放什么样的内容?
在C++中,内存分成5个区,他们分别是堆、栈、全局/静态存储区、常量存储区和代码区:
1)栈区,当代码运行进函数时,函数内的局部变量的内存是在在栈上分配的,函数执行结束时这些栈内存会自动被释放。此外,函数调用时的传递的参数,是通过栈内存传递给被调用函数的,这点查看汇编代码一目了然。
2)堆区,通过malloc或new动态申请的内存都是在堆上分配的,这些堆内存需要程序员自行去管理,调用free或delete去释放。如果代码中不释放,则在程序结束运行时由操作系统去释放。
3)全局/静态存储区,它主要存放静态数据(局部static变量,全局static变量)和全局变量,这些变量的内存在程序启动进入main函数之前就分配好了,这块内存在程序的整个运行期间都存在,在程序退出时释放。
4)常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量字符串,不允许修改。
5)代码区,存放程序的二进制代码。exe程序启动时系统会将exe程序依赖的所有二进制文件及exe文件加载到进程空间中,这些二进制文件中存放的是二进制代码,这些二进制代码占用的内存,是代码段内存,是从进程的虚拟内存空间划拨的。
4、指针与引用的区别?
指针在指向某个对象后,可以更改其指向,即可以再指向其他对象。而引用一旦确定引用关系后,是不能修改指向的。引用必须在定义的时候就确定引用关系,引用类型的变量在定义时必须初始化。
int a = 1;
int b = 2;
int* p = &a;
p = &b; // 指针可以更改其指向的对象
int& c = a; // 定义时就要初始化,就要确定引用关系
int& c;
c = a; // 这是错误的,不能定义之后再去初始化
5、struct结构体和class类的区别是什么?
比如如下的结构体:
// 设备信息
struct TDeviceInfo
{
char achDeviceId[64]; // 设备id
char achDeviceName[64]; // 设备名称
int nDevType; // 设备类型
};
struct结构体和class类的区别如下:
1)使用struct时,它的成员的默认访问权限是public,而class的成员默认是private的;
2)struct的继承默认是public继承,而class的继承默认是private继承;
3)class可以使用模板,而struct不能。
6、C++中const的使用场景有哪些?
const关键字的使用场景如下:
1)const可以用来修饰变量,变量值是不可修改的,比如:
const int = 5;
2)可以用来修饰函数的参数,函数中不得修改变量的值,比如:
int AddNum( const int a, const int b );
3)可以用来修饰函数返回值的类型,返回值是不可修改的,比如:
const char* GetString();
4)可以用来修饰类的成员函数,则该函数不能内不能修改类成员变量的值,比如:
class ClassA
{
public:
ClassA();
~ClassA();
public:
int GetLength() const;
private:
int m_nLength;
}
7、inline内联函数与宏的异同点有哪些?
实现两个int变量求和的**内联函数**如下:
inline int AddNum(int a, int b)
{
int nSum = a + b;
return nSum;
}
求两个整型数值最大值的**宏**:
// 求两个数中较小的数
#define min(a,b) (((a) < (b)) ? (a) : (b))
函数调用时会有调用的开销,比如参数的入栈出栈操作、保护线程和恢复现场操作等,所以引入了内联函数,避免了函数调用的开销。内联函数实现不宜过长,一般不超过10句代码。
对于内联函数和宏,共同点是,在编译时编译器会直接将它们的实现部分直接替换到调用处。内联函数和宏有很多区别:
1)内联函数在编译时展开,而宏在预编译时展开。
2)在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
3)内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能。
4)宏不是函数,而inline作用的是函数。
5)宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性,而内联函数不会出现二义性。
6)inline可以不展开,宏一定要展开。因为inline指示对编译器来说,只是一个建议,编译器可以选择忽略该建议(比如编译器发现函数中有循环等操作时会自动忽略内联关键字),不对该函数进行展开。
8、STL模板库的相关问题
STL标准模板库已经广泛地应用到C++程序中,STL相关内容也是面试常考的问题。
8.1、常用的STL容器有哪些?容器中有哪三个重要的概念?
STL中常用的容器有vector、list、map、deque、set、queue等,所有的容器可以见下图:
STL中有三种概念:容器、迭代器和算法函数。
8.2、算法函数你知道吗?如何提高stl容器的遍历效率?
常用的算法函数有sort、count、count_if、find、find_if、remove_copy和remove_copy_if等。这些算法函数比使用迭代器去for循环遍历容器要快很多,在数据量比较大的情况下效率比较高,可以有效地提高STL容器的遍历效率。
8.3、哪两种容器中的数据是有序存放数据的?有什么好处?
set和map中存放的数据是有序的,数据的有序排列有利于提升查找的效率。
8.4、vector和数组有什么区别?
vector使用的是一段连续的内存,这点和数组是类似的,但vector是可变长的“数组”,当内存空间不够时会自动扩充内存长度。正因为其使用的时候一段连续的内存,所以可以向数组那样使用数组下标去访问。
vector和数组类似,拥有一段连续的内存空间。vector申请的是一段连续的内存,当插入新的元素内存不够时,通常以2倍重新申请更大的一块内存,将原来的元素拷贝过去,释放旧空间。因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。
STL中的vector是封装了动态数组的顺序容器。不过与动态数组不同的是,vector可以根据需要自动扩大容器的大小。具体策略是每次容量不够用时重新申请一块大小为原来容量两倍的内存,将原容器的元素拷贝至新容器,并释放原空间,返回新空间的指针。
8.5、vector和list有什么区别?
vector和list主要有以下几方面的区别
1)vector使用的是一段连续的内存,类似于数组,可以像数组一样使用下标访问列表中的元素;list使用的内存不是连续的,是用双向链表实现的。
2)vector支持使用下标的方式去随机访问元素,list不支持。
3)vector在中间节点进行插入和删除元素时会触发内存拷贝,list不会。
4)vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。
5)vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。
9、了解C++11标准中的内容吗?都知道哪些C++11特性?
重量级的C++11标准推出已经很多年了,新标准中推出的部分已经被大家广泛的采用,特别是一些大型的开源代码会大量的采用C++11标准中的内容,比如Chromium浏览器内核开源项目、WebRTC开源项目等。很多面试官比较喜欢问C++11标准相关的内容。
关于C++11的介绍:
C++11(也称C++2.0、Modern C++) 是继C++98(C++1.0) 之后的第二个重大C++标准更新,其对C++的改变是全方位的,有人也说C++11是一门新的语言。C++11增加了非常多的新特性,而这些新特性对于开发效率的提升非常明显。
下面简单罗列一下部分常用的C++11标准特性:
1)自动类型推导auto:auto的自动类型推导用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作。
2)nullptr:nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0,而nullptr是void*类型的。
3)lambda表达式:它类似Javascript中的闭包,它可以用于创建并定义匿名的函数对象,很好地简化了函数编程的工作。
4)智能指针auto_ptr、unique_ptr、shared_ptr和weak_ptr,智能指针在开源项目中使用的比较多。
5)override关键字,显示的声明重写了父类的方法。
10、你用过什么设计模式?
设计模式在项目代码中会或多或少的用到,面试时可能会问到对设计模式的掌握情况。
设计模式有20多种,但很多模式大家可能都没使用过,这里只要大概列举几个用过的设计模式即可,比如单例模式(单例类似于全局变量)、简单工厂模式(根据不同的类型创建不同的子类,比如实现截图时直线、曲线、矩形、椭圆等不同图形绘制)、观察者模式(需要关注的通知的去注册一下,会收到通知回调)。
** 这里需要注意一下,要会手写熟悉的设计模式的实现代码,面试官可能会让你手写这些实现代码,**以考察对设计模式细节的掌握程度。比如,实现单实例时,需要将构造函数设置为私有的,外部不得使用类去定义类对象,必须调用获取实例对象的接口。定义单实例时可以使用static静态对象的方式,也可以去动态去new一个对象,然后将对象保存到static静态指针变量中。定义静态变量的实现如下:
// 1、实现方式1:本地数据单实例类,存储本地需要的数据
class CLocalLogic
{
public:
~CLocalLogic(void);
static CLocalLogic& Instance()
{
static CLocalLogic localData;
return localData;
}
private:
CLocalLogic(void);
};
// 2、实现方式2:动态去new对象的代码如下:
class CLocalLogic
{
public:
~CLocalLogic(void);
static CLocalLogic* GetInstance()
{
if ( s_pInstance = NULL )
{
s_pInstance = new CLocalLogic;
}
return s_pInstance;
}
private:
CLocalLogic(void);
private:
static CLocalLogic* s_pInstance;
};
版权归原作者 dvlinker 所有, 如有侵权,请联系我们删除。