0717百度面经
1. python跟C++的区别
- 语言类型不同
- C++是编译性编程语言,编程型语言在程序执行前有一个单独的编译过程,将程序翻译成机器语言,以后执行的时候就不用再编译,直接运行可执行文件
- python是解释性语言,解释型语言是指使用专门的解释器对源程序进行逐行解释成特定平台的机器码,并立即执行。每次执行解释性语言程序的时候都需要重新解释再执行,所以它的运行效率通常比较低,而且不能脱离解释器执行
- 执行效率不同
- C++执行效率高
- python执行效率低
- 开发效率不同
- C++开发效率低,编程难度大
- python开发效率高,编程难度小
- 内存管理机制不同
- python有被称为“垃圾收集器”的自动内存管理机制,不允许直接进行内存处理操作
- C++里则没有这样的机制,并且所有内存管理操作都需要自行处理
2. 对称加密和非对称加密的区别
- 加密和解密使用的密钥不同
- 对称加密双方使用相同密钥
- 非对称加密双方分别使用公钥和私钥
- 成本不同
- 对称加密算法在加密和解密过程中只涉及一个密钥,算法的实现成本较低
- 而非对称加密算法涉及两个密钥,其中一个是非公开的,因此算法的实现成本较高
- 加解密速度不同
- 对称加解密速度较快,适合数据比较长的时候使用
- 非对称加解密速度较慢,适合对少量数据的使用
- 传输的安全性不同
- 对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。
- 而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,即便攻击者获得了公钥,也无法解密加密的数据。
3. AES算法几种工作模式
- AES加密算法
AES的轮函数每一轮迭代的结构都一样,由4种变换组成:字节替换、行移位、列混合、轮密钥加 - 分组加密的工作模式
块加密模式
- ECB:消息分成相互独立的加密模块,每块独立加密。特点:同样的明文会出现相同的密文,适合短数据加密
- CBC(分组链接模式):消息块M1跟初始向量IV异或后加密得密文C1,消息块M2和C1异或后加密得密文C2。特点:适合用于加密较长的消息
流加密模式:转化为流密码,不需要对密码进行填充 - CFB(密码反馈模式):IV——移位寄存器加密后,选择前j比特和消息P1异或得C1,将移位寄存器左移j位并放入密文C1……
- OFB(输出反馈模式):OFB是将加密算法的输出反馈到移位寄存器,CFB是将密文反馈到移位寄存器。OFB的优点是比特错误不会被传播,而CFB的比特错误会被放到移位寄存器里,影响接下来的解密过程
CTR(计算器模式):Counter加密后和明文P1异或得C1,Counter+1:加密后和明文P2异或后得C2。特点:可以并行加密。
4. C++内存分区
C++在执行时,将内存划分为4个区域:
- 代码区:存放函数体的二进制代码
- 全局区:存放全局变量、静态变量和常量
- 栈区:由编译器自动分配释放,存放函数的参数值、局部变量
- 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
- 程序运行前:
程序编译后,生成了exe可执行程序,未执行程序前分为两个区域- 代码区:存放CPU执行的机器指令;是共享的,对于频繁执行的程序,在内存中有一份代码就行;是只读的,防止程序意外修改指令
- 全局区:存放全局变量和静态变量+常量区:存放const修饰的全局常量和字符串常量等
- 程序运行后:
- 栈区:由编译器自动分配和释放,存放函数的参数值、局部变量。所以注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。
- 堆区:由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
5. 32位系统中堆通常在的地址范围是多少,大概有多大
对于linux来说,地址由低向高分别是:保留区,代码段,数据段,BSS段,堆,文件映射区,栈,内核空间
堆的大小范围可能在几百MB到2-3GB之间
6. C++中的智能指针
unique指针怎么做到不能被复制的
7. 指针传递、值传递和引用传递的区别
- python有没有值传递和引用传递的区别:python中没有严格的定义值传递与引用传递
- python中的变量没有类型,变量相当于一个指针,可以指向任何类型的对象,也就是变量引用了某个对象;python对象是有类型的,一般看变量是什么类型需要看其引用的对象是什么类型。
- 总的看来,函数传递参数都可以看做是引用传递的(因为python变量相当于指针,传递指针就相当于传递了地址的引用),只不过因为python中的有些对象是不可变的,因此让有些引用传递的过程中又像是值传递的。
- 当python中的函数传递过来的是不可变的值时(比如数字常量、元组和字符串),相当于 C语言中的值传递的;若传递过来的参数是可变的(如列表、字典等),则相当于引用传递
- 可变类型与不可变类型
- 不可变类型:不可变变量的值一旦创建,就不能被修改。如果你尝试修改一个不可变对象的值,Python 将会创建一个新的对象。Python 中的不可变对象包括整数(int)、浮点数(float)、字符串(str)、元组(tuple)等。
- 可变类型:可变变量的值可以在原地修改,而不会创建一个新的对象。Python 中的可变对象包括列表(list)、字典(dict)、集合(set)等
1
2
3
4
5
6
7
8
9
10
11def modify_value(x):
print(f"变量x修改前地址:{id(x)}")
x = x + 10
print(f"变量x修改后地址:{id(x)}")
print("函数内部修改后的值为:", x)
# 调用函数
value = 5
print(f"变量value地址:{id(value)}")
modify_value(value)
print("函数外部原始值为:", value)
8. C++编译链接的过程
- 预处理阶段:预处理器主要处理以#号开头的预处理指令,包括头文件包含、宏定义、条件编译等等
- 头文件包含:预处理器会根据
#include
指令将需要的头文件内容插入到当前源文件中 - 宏替换:预处理器会识别并替换
#define
指令定义的宏 - 条件编译:预处理器根据
#ifdef/#ifndef
等条件编译指令来决定是否编译某段代码 - 在这个过程中,预处理器还会处理行链接、删除注释等工作
- 头文件包含:预处理器会根据
- 编译阶段:编译器将预处理后的源代码转换成汇编语言代码
- 词法分析:编译器首先将源代码分解为一系列的tokens
- 语法分析:编译器根据语言的语法规则,将tokens组合成语法树或者中间表示
- 语义分析:编译器检查语法树或者中间表示的语义,确保类型正确、变量已定义等
- 优化:编译器可能会进行一系列优化,以提高生成代码的性能或减少其大小
- 最终编译器生成汇编语言代码文件(通常是以.s或.asm为扩展名)
- 汇编阶段:汇编器将编译阶段生成的汇编代码转换成机器指令
- 汇编指令:汇编器将每一条汇编指令翻译成机器指令
- 最终,汇编器生成目标文件(通常以.o、.obj或.elf为扩展名)。这些目标文件包含了机器码、符号表和其他代码相关的信息
- 链接阶段:链接器将多个目标文件和库文件(如静态库和动态库)结合起来,生成最终的可执行文件。地址重定位:链接器解决函数和变量之间的引用关系,确定他们在内存中的地址。
- 符号解析:链接器处理目标文件中定义的符号(如函数和变量)和引用的符号,确保他们之间的正确匹配
- 库文件链接:如果程序中使用了外部库,链接器会将这些库与目标文件链接起来
- 整个编译链接过程确保了源代码从高级语言形式逐步转换为机器可执行的形式,并处理了代码中的依赖关系和符号引用。最终生成的可执行文件可以在目标平台上运行
9. C++中static关键字的作用
- static最重要的作用:隐藏(普通函数、普通变量)
- 当同时编译多个文件时,所有未加
static
的全局变量和函数都具有全局可见性,其他源文件也能访问 - 如果加了
static
,就会对其他源文件隐藏,避免命名冲突
- 当同时编译多个文件时,所有未加
- static的第二个作用是改变变量的存储位置:静态存储区
- 静态存储区存储的有全局变量和static变量
- 存储在静态存储区的变量的特点:
- 在程序刚开始运行的时候就完成初始化,也是唯一的一次初始化
- 静态数据区中所有变量初始值默认为0
- 具有持久性
- static修饰类成员
静态数据成员是类的成员不是对象的成员,所以有以下作用- 类的静态成员函数属于类而不是类的对象,所以没有this指针,不能访问非静态数据和非静态成员函数,也不能将静态成员函数定义为虚函数
- 类的静态成员数据是静态存储的,所以必须进行初始化,静态成员初始化和一般成员初始化不同,在类外初始化,格式如下:
<数据类型> <类名>::<成员名>=<值>
- 静态成员为父类和子类共享。为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响
Q:在头文件中把变量声明为static变量,在引用该头文件的源文件中可以访问该变量吗
A:可以,声明static变量一般是为了在本cpp文件中的static变量不能被其他cpp引用。但是对于头文件,因为cpp文件中包含了该头文件,相当于该static变量在本cpp文件中也可见。而且当多个cpp文件包含该头文件时,static变量在各个cpp是独立的
Q:为什么静态成员函数不能修饰为const?
A:C++的类中,const修饰函数表示函数不能修改成员变量的值,而static函数没有this指针,不能访问非静态成员变量, 矛盾
Q:为什么不能在类的内部定义以及初始化static成员变量,必须放到类外定义?
A:因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,矛盾
Q:为什么static关键字只能出现在类内部的声明语句中,而不能重复出现在类外的定义中
A:如果类外定义函数加了static,会导致该函数只能在本文件中使用,而类本来就是为了给程序里各个地方用的,其他地方使用是包含类的头文件,而无法包含类的源文件