c++面经1

本文详细探讨了C++中的核心概念,包括数组与链表的区别、new与malloc的区别、构造函数与析构函数的虚函数特性、常量指针与指针常量的差异、拷贝构造函数与赋值运算符重载的使用、C++源文件编译过程、#include指令的不同以及内存管理方式。同时,深入阐述了指针与引用的本质差异。

1.数组和链表的区别

二者都属于一种数据结构
从逻辑上看:
1):数组是一种线性表数据结构。他用一组连续的内存空间,来存储一组具有想同类型的数据,最大的特点是支持随机访问,但数组必须事先定义固定的长度(元素个数),不能适应数据动态增加的情况,当数据增加时,可能超过原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取
2):链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表由一系列节点组成,链表动态地进行存储分配,可以适应数据动态地增减问题,且可以方便的插入,删除数据项。(数组中插入,删除数据项时,需要移动其他数据项,非常繁琐)链表必须根据 next指针找到下一个元素。

从内存存储来看:
1):数组从栈中分配空间,对于程序员来说方便快捷,但是自由度小
2):链表从堆上分配空间,自由度大但是申请管理比较麻烦

从时间复杂度来看:
数组利用下标定位,时间复杂度为O(1),链表定位元素的时间复杂度为O(n)
数组插入或删除元素的时间复杂度为O(n),链表插入或删除元素的时间复杂度为O(1)

2.new和malloc的区别 free和delete的区别

malloc和new从申请的内存所在位置,返回类型安全性,内存分配失败时的返回值,是否需要指定内存大小这四点来区分
1):申请的内存所在位置不同
new操作符从自由存储区上为对象动态分配内存空间,自由存储区是c++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区
malloc从堆上动态分配内存,堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序IDE内存动态分配,C语言使用malloc从堆上分配内存,使用free释放分配的对应内存
2):返回类型安全性不同
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无需进行类型转换,故new是符合类型安全性的操作符
malloc内存分配成功则返回void*,需要通过强制类型转换将void*指针转换成我们需要的类型
3)内存分配失败时的返回值不同
malloc分配内存失败时,返回NULL
new内存分配失败时,会抛异常,他不会返回NULL;
4)是否需要指定内存大小不同
使用new操作符申请内存时无须指定内存块的 大小,编译器会根据类型信息自行计算
malloc则需显式的指出所需内存的尺寸

free用于释放new分配的内存,和new是成对存在的 dalete用于释放malloc分配的内存,和malloc成对调用
使用free释放时需要判断指针是否为空,delete不需要
free释放内存,但是不调用对象的析构函数。而delete不仅释放内存,还调用对象的析构函数
delete和new是对对象的操作,malloc和free是对内存空间的操作

new和delete的实现原理:
Tp=new T;
(1):调用void
operator new(size_t size/所要申请空间类型所占的字节数/)----->该参数由编译器传递
采用malloc循环申请空间:
申请成功---->返回空间的首地址
申请失败—>说明系统堆内存空间不足
a:用户自己想办法---->提供内存空间不足的应对措施—>执行用户空间不足的应对措施—>继续malloc
b:直接抛出bad_alloc异常---->如果没有对异常进行处理就会程序崩溃
operator new申请空间时,要么返回空间的首地址,要么抛异常—>不会返回nullptr
(2):调用T所对应的构造函数来初始化对象
delete p;
(1):调用析构函数清理对象中的资源
(2):调用void operator delete(void* p)来释放p所指向的堆空间 在operator delete函数中,实际调用free来释放堆空间

3.如何判断俩个结构体是否相等

通过重载操作符“==”
不能使用memecpy来判断两个结构体是否相等:memcpy是通过逐个字节进行比较的,二struct存在字节对齐,字节对齐时补的内容是随机的 ,会产生垃圾值,所以无法比较

4.构造函数和析构函数是否可以声明为虚函数,加以解释

构造函数不能声明为虚函数
原因:虚函数的调用需要虚函数表指针,而该指针存放在对象的内存空间中,那么问题来了,若将构造函数声明为虚函数,调用构造函数需要虚函数表指针,那么由于对象还未创建,还没有内存空间,更没有虚函数表指针来调用虚函数–构造函数。
析构函数可以为虚函数,而且当要是用基类指针或引用调用子类时,最好将基类析构函数声明为虚函数,否则可能存在内存泄漏问题
具体来说,如果派生类中申请了内存空间,并在其析构函数中对对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会出发动态绑定,因而只会调用基类的析构函数,而不会掉用派生类的析构函数,那么在这种情况下派生类所申请的空间就不能得到释放从而产生内存泄漏。所以,为了防止内存泄漏,c++中基类的析构函数应采用虚析构函数。
举例说明:
子类B继承自基类A; Ap=new B; delete p;
1):此时,如果类A的析构函数不是虚函数,那么delete p;将会仅仅调用A的析构函数,只释放B对象中A部分,而派生出的新部分并没有释放掉
2):如果类A的析构函数是虚函数,delete p;将会先调用B的析构函数,在调用A的析构函数,释放B对象的所有空间
补充:B
p=new B;deletep;也是先调用B的析构函数,再调用A的析构函数。

5.常量指针和指针常量区别

1):本质:
指针常量:本质上是一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量
常量指针:本质上是指针,常量表示指针指向的内容,说明该指针指向一个“常量

2):地址:
指针常量:在指针常量中,指针自身的值是一个常量,不可改变,始终指向一个地址,在定义的同时必须初始化
常量指针:指针可以指向其他地址
3):内容
指针常量:指向的内容可以被修改
常量指针:在常量指针中,指针指向的内容是不可被修改的
在这里插入图片描述

6 拷贝构造函数为什么要传引用,赋值运算符重载也必须传引用吗

拷贝构造函数传引用不传值是怕引起拷贝构造函数的无限递归
从逻辑角度来看,因为参数的传递本身就是复制,如果不使用引用类型,拷贝构造函数在传参是就又会调用拷贝构造函数,就会造成无限递归
赋值运算符重载可以传值也可以传引用,传值会多出来一次拷贝构造函数,所以尽量传引用,

7.c++源文件从文本到可执行文件经历的过程

预处理阶段:对源代码文件包含关系(头文件)预编译语句(宏定义)进行分析和替换,生成预编译文件
编译阶段:将经过预处理后的预编译文件转换为特定的汇编代码,生成汇编文件
汇编阶段:将编译阶段生成的汇编代码转换为机器代码,生成可重定位目标文件
链接阶段:将多个目标文件及所需要的库链接成最终可执行目标文件

8.#include<>和#include" "的区别

(1).引用的头文件不同
#include<>引用的是编译器的类库路径里面的头文件
#include"“引用的是你程序目录的相对路径中的头文件
(2):用法不同
#include<>用来包含标准头文件
#include“ ”用包含非标准头文件
(3):调用文件的顺序不同
#include<>编译程序会先到标准函数库中调用文件
#include“ ”编译程序会先到当前目录下调用文件
(4):预处理程序的指示不同
#include<>指示预处理程序到预定义的缺省路径下寻找文件
#include” "指示预处理程序先到当前目录下寻找文件,再到预定义的缺省路径下寻找文件

9.c++内存管理方式:

c++有三种内存管理方式:
(1):自动存储
在函数内部定义的常规变量使用的自动存储空间,通常存储在栈中,随函 数的产生而产生,函数的消亡而消亡
(2):静态存储
是在整个程序执行期间都存在的存储方式。使变量称为静态存储的方式有 两种:在函数外面定义它 声明变量时使用static
(3):动态存储
数据的生命周期不完全受程序或函数的生命周期控制,可以通过new和 delete运算符来管理,也可以使用库函数malloc和free,在c++中被称为 自由存储区或堆区

10:指针和引用的区别

指针就是一种指针类型的变量,其实就是一个空间存储了另一个空间的地址,通过地址来访问这个空间里的数据,所以指针的本质就是地址(引用也是通过指针来实现的)
引用的本质其实是一个别名,通过这个别名来访问空间
(1):程序为指针变量分配内存区域,却不为引用分配内存区域
(2):引用在定义需要初始化,之后无法改变,而指针可以发生改变
(3):指针在使用时前面需要解引用(*),引用不需要
(4):引用不能为空,指针可以为空
(5):引用没有const,指针有const,const的指针不能改变
(6):“sizeof引用”得到的是所指向变量(对象)的大小,“sizeof指针”得到的是指针的 大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值