1.c++中struct和class的区别
- struct 一般用于描述一个
数据结构集合
,而 class 是对一个对象数据的封装
。 - struct 中默认的访问控制权限是
public
的,而 class 中默认的访问控制权限是private
的。 - 在继承关系中,struct 默认是
公有继承
,而 class 是私有继承
。 - class 关键字可以用于
定义模板参数
,就像 typename,而struct 不能
用于定义模板参数。
2.C++中指针和引用的区别
- 指针是存储
变量地址
的变量;引用是变量的别名
。 - 指针变量定义时不必=初始化;引用定义时必须初始化,不然会报错。
- 指针变量定义时可以初始化为NULL;引用不能初始化为NULL,不然报错。
- const修饰指针变量,const放在之前,指针变量所指向变量的值不可改变,指针值可以改变;const放在之后,指针变量所指向变量的值可以改变,指针值不可以改变;
- const修饰引用,const放在&之前,不能修改引用所表示的变量的值;const放在&之后,const的作用被忽略,可以修改引用所表示的变量的值。
- sizeof运算符作用于指针变量得到指针变量自身大小;作用于引用,得到引用所指向的变量的大小。
- 指针可以有多级,引用只有一级。
- 指针的自增、自减表示指向下一个同类型变量的地址,一般用于指向数组的指针;引用的自增、自减表示指向变量值的增、减。
3.extern “c”的作用
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示
编译器这部分代码按C语言的进行编译,而不是C++的。
4.深拷贝、浅拷贝、写时拷贝
- 深拷贝:不仅拷贝指针,对指针指向的内容进行拷贝,深拷贝后两个指针指向两个不同的地址。
- 浅拷贝:只是对指针的拷贝,拷贝后两个指针指向同一个内存空间。
- 写时拷贝:内核为新生成的子进程创建虚拟空间结构,来复制于父进程的虚拟地址结构,但不给这段分配物理内存,它们共享父进程的物理空间,当父进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
类似于陪读,陪着学习,但不占学习名额。
5.malloc/new、free/delete各自底层实现原理
在使用的时候 new和delete 搭配使用,malloc 和 free 搭配使用。
- 属性:
- malloc/free 是库函数,需要头文件的支持。
- new/delete 是关键字,需要编译器的支持参数。
- new 申请空间时,无需指定分配空间的大小,编译器会根据类型自行计算。
- malloc 在申请空间时,需要确定所申请空间的大小返回值。
- new 申请空间时,返回的类型是对象的指针类型,无需强制类型转换,符合类型安全的操作符。
- malloc 申请空间时,返回的是 void* 类型,需要进行强制类型的转换,转换为对象类型的指针。
- 分配失败:new 分配失败时,会抛出 bad_alloc 异常,malloc 分配失败时返回空指针
- 重载:new/delete 支持重载,malloc/free 不能进行重载
- 自定义类型实现:new 首先调用 operator new 函数申请空间(底层通过 malloc 实现),然后调用构造函数进行初始化,最后返回自定义类型的指针;delete 首先调用析构函数,然后调用operator delete 释放空间(底层通过 free 实现)。malloc/free 无法进行自定义类型的对象的构造和析构。
- 内存区域:new 操作符从自由存储区上为对象动态分配内存,而 malloc 函数从堆上动态分配内存。(自由存储区不等于堆)。
- ==new类型是安全=的,而malloc不是。
6、数组和链表的区别
数组:
- 逻辑结构:
- 数组在内存中连续;
- 使用数组之前,必须实现固定数组长度,不支持动态改变数组大小;
- 数组元素增加时,有可能会数组越界;
- 数组元素减少时,会造成内存浪费;
- 数组增删时需要移动其他元素
- 内存结构:数组从栈上分配内存,使用方便,但是自由度小
- 访问效率:数组在内存中顺序存储,可通过下标访问,访问效率高
- 越界问题:数组的大小是固定的,所以存在访问越界的风险
• 使用场景:
◦ 空间:数组的存储空间时栈上分配的,存储密度大,当要求存储的大小变化不大时,且可以事
先确定大小,宜采用数组存储数据
◦ 时间:数组访问效率高。当线性表的操作主要是进行查找,很少插入和删除时,宜采用数组结
构
链表: - 逻辑结构:
- 链表采用动态内存分配的方式,在内存中不连续
- 支持动态增加或者删除元素
- 需要时可以使用malloc或者new来申请内存,不用是使用free或者delete来释放内存
- 内存结构:链表从对上分配内存,自由度大,但是要注意内存泄漏
- 访问效率:链表访问效率低,如果想要访问某个元素,需要从头遍历
- 越界问题:只要可以申请得到链表空间,链表就无越界风险
- 使用场景:
- 空间:链表的存储空间是堆上动态申请的,当要求存储的长度变化较大时,且事先无法估量数
据规模,宜采用链表存储。 - 时间:链表插入、删除效率高,当线性表要求频繁插入和删除时,宜采用链表结构。
- 空间:链表的存储空间是堆上动态申请的,当要求存储的长度变化较大时,且事先无法估量数
7.野指针和悬空指针的区别
- 野指针:访问一个已删除或访问受限的内存区域的指针,野指针不能判断是否为NULL来避免。指针没有初始化,释放后没有置空,越界。
- 悬空指针:一个指针的指向对象已被删除。
8.如何避免野指针
- 当指针没有做初始化,即没有指向时,将指针指为NULL。一方面可以提醒自己这个指向NULL的指
针不可操作不可访问,另一方面NULL这个标记便于我们检查和避免野指针;初始化为NULL的目
的:一是出现段错误时易改错,二是(void *0) 是0地址,是不允许操作,不允许访问的。 - 当想给指针赋值时,检查是否已经给他分配了内存空间,如果没有分配就再用malloc分配。
- 给指针分配完内存后,不使用时再利用free()函数清空内存空间(清空原来的缓冲区),并再将指
针指为NULL。
9.const和define的区别
- const生效于编译的阶段;define生效于预处理阶段。
- const定义的常量,在C语言中是存储在内存中、需要额外的内存空间的;define定义的常量,运行时是直接的操作数,并不会存放在内存中。
- const定义的常量是带类型的;define定义的常量不带类型。
28、左值引用和右值引用的区别
可以取地址的,有名字的,非临时的就是左值;
不能取地址的,没有名字的,临时的就是右值;
可见立即数,函数返回的值等都是右值;而非匿名对象(包括变量),函数返回的引用,const对象等都是左值。
在汇编层面右值引用做的事情和常引用是相同的,即产生临时量来存储常量。但是,唯一 一点的区别是,右值引用可以进行读写操作,而常引用只能进行读操作。
右值引用的存在并不是为了取代左值引用,而是充分利用右值(特别是临时对象)的构造来减少对象构造和析构操作以达到提高效率的目的