C++ 常见面试题(每周更新)

1.指针常量和常量指针的区别

指针常量:指针本身是常量。该指针只能指向某个常量,不可再指向其他常量。(指针地址不可变,值可变)
(注:指针常量在定义时要赋初值)

int a = 0,b = 0;
int* const p = &a;
*p = 1; //正确,可以修改值
p = &b; //错误,不可改变地址

常量指针:指向常量的指针。该指针指向一个常量,常量的值不可变,不可以通过该指针修改其值,但是该指针可以指向其他常量。(指针地址可以变,值不能变)

int a = 0,b = 0;
const int *p = &a;
*p = 1; //错误,不可修改常量值
p = &b; //正确,可以指向另一个常量

区分记忆:如果关键字 const 出现在 * 号左边,表示被指物是常量,侧重点是常量,值不可变;如果出现在 * 号右边,表示指针自身是常量,侧重点是指针,地址不可变;如果出现在 * 号两边,表示被指物和指针都是常量,地址和值都不可变。(简化记忆:const 与 * 号,谁在左边就以谁为侧重点

2.动态库和静态库的区别

静态库和动态库最本质的区别是:该库是否被编译进目标程序内部。
静态库:一般扩展名为(.a或.lib),这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,不再需要向外部函数要求读取函数库的内容,但是从升级难易程度来看,明显没有优势,如果函数库更新,需要重新编译。
动态库:一般扩展名为(.so或.dll),与静态函数库被整个捕捉到程序中不同,动态函数库在编译的时候,在程序里只有一个指向的位置而已,也就是当可执行文件需要使用到函数库机制的时候,程序才会读取函数库使用,也就是说可执行文件无法单独运行。这样从产品升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件。
总结:从产品化的角度,发布的算法库或功能库尽量使用动态库,这样方便更新和升级,不必重新编译整个可执行文件,只需要新版本动态库替换掉旧的动态库即可。从函数库集成的角度,若要将发布的所有子库集成为一个动态库向外提供接口,那么就需要将所有子库编译成一个静态库,这样所有子库就可以全部编译进动态库中,由最终的一个集成库向外提供功能。

3.头文件中的ifndef/define/endif有什么作用?

这是C++预编译头文件保护符,保证即使文件被多次包含,头文件也只定义一次。

4.请描述进程和线程的区别

(1)进程是程序的一次执行,线程是进程中的执行单元;

(2)进程间是独立的,这表现在内存空间、上下文环境上,线程运行在进程中;

(3)一般来讲,进程无法突破进程边界存取其他进程内的存储空间;而同一进程所产生的线程共享内存空间;

(4)同一进程中的两段代码不能同时执行,除非引入多线程。

5.二叉树的几种遍历方式

前序: 根结点 —> 左子树 —> 右子树
中序: 左子树—> 根结点 —> 右子树
后序: 左子树 —> 右子树 —> 根结点
将子二叉树都看作一个整体,一个二叉树包含一个根节点和两个叶子节点(左枝和右枝),
以前序为例,ABC三个节点的遍历顺序为:A B C (根结点 —> 左子树 —> 右子树),由于B节点下面有子树,按前序遍历为 B D E ,所以遍历顺序变成了 A B D E C,E下又有子树 H,遍历顺序变成了 A B D E H C,右子树同样按前序遍历。最终的遍历顺序为:A B D E H C F I G

在这里插入图片描述

在上面这个二叉树中几种遍历方式对应的顺序:
前序: A B D E H C F I G
中序: D B H E A F I C G
后序: D H E B I F G C A

6.C++ static关键字有哪些作用?

全局静态变量:位于静态存储区,程序运行期间一直存在,对外部文件不可见。(表明一个全局变量只对定义在同一文件中的函数可见。)

局部静态变量:位于静态存储区,在局部作用域可以访问,离开局部作用域之后static变量仍存在,但无法访问。(表明该变量的值不会因为函数终止而丢失。)

静态函数:即在函数定义前加static,函数默认情况下为extern,即可导出的。加了static就不能为外部类访问。注意不要在头文件声明static函数,因为static只对本文件有效。(表明该函数只在同一文件中调用。)

类的静态成员:可以实现多个不同的类实例之间的数据共享,且不破坏隐藏规则,不需要类名就可以访问。类的静态存储变量是可以修改的。可以通过<对象名>::<静态成员>进行访问。(表明对该类所有对象这个数据成员都只有一个实例。即该实例归所有对象共有。)

类的静态函数:不能调用非静态成员,只可以通过对象名调用<对象名>::<静态成员函数>(意味着一个静态成员函数只能访问它的参数、类的静态数据成员和全局变量)

7. 什么是内存抖动

内存页面的频繁更换,导致整个系统的效率急剧下降这个现象称为内存抖动。
抖动一般是内存分配算法不好,内存太小或者程序的算法不佳引起的页面频繁从内存调入调出。

8. 文件操作的唯一依据是什么

文件操作的唯一依据是文件句柄,文件句柄是唯一标识,相当于id。
文件描述符:open 函数的返回值,返回当前操作文件的句柄,后续通过文件描述符(文件句柄)来读文件或者写文件。

int open(const char *pathname , int flags , mode_t mode);
ssize_t read(int fd , void *buf , size_t count);
ssize_t write (int fd,const void *buf ,size_count);

在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。
该函数取回一个顺序号,即文件句柄(file handle),该文件句柄对于打开的文件是唯一的识别依据。
要从文件中读取一块数据,应用程序需要调用函数ReadFile,并将文件句柄在内存中的地址和要拷贝的字节数传给操作系统。
当完成任务后,再通过调用系统函数来关闭该文件。

9.new和delete的使用方法

new 和 delete运算符是用于 动态分配 撤销内存 的运算符。

int *a = new int //即为将一个int类型的地址赋值给整型指针a
int *a = new int(5) //作用同上,但是同时将整数空间赋值为5

int *a = new int[100];    //开辟一个大小为100的整型数组空间 一维
int **a = new int[5][6]  //二维
  1. 删除单变量地址空间
int *a = new int;
delete a;   //释放单个int的空间
  1. 删除数组空间
int *a = new int[5];
delete []a;    //释放int数组空间

10.new和malloc的区别

1,new是操作符,malloc是函数;
2,new开辟内存失败抛出异常,malloc申请内存失败返回NULL;
3,new开辟的内存大小不需要指定,malloc需要指定
4,new开辟的内存的类型会自动推导,不需要强转,malloc需要强转; malloc与free

(int*)malloc(4);
// 申请了一个四个字节的空间并且规定该空间为一个int型变量空间,而不是别的。
int *p =(int*)malloc(4);
// 由于malloc返回一个 空间地址,所以需要一个相应类型的指针来接收改地址
int *p;
p=(int*)malloc(4);
//也可以分写

11. C++中关于int p和 int p的区别?

对于int p,其和int p 的含义一样,都表示int类型的指针变量p。但是将 声明符 " * " 紧跟着变量名是一种更容易理解的做法。
例如

 int* p1, p2;

表示含义是p1是一个int型的指针,p2是一个int型变量。而不是p1,p2都是指针变量,它们共用的是基本数据类型部分。
如果写成 int *p1,p2; 则和上式表示的含义完全一样,但是更加清晰,不会造成误导。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聪明小張

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值