1、说说C语言和C++的区别
1.C语言是面向过程编程语言;C++是面向对象编程语言
2.C语言是C++的子集,C++可很好的兼容C语言。但是C++又引入的很多新的特性比如引用、智能指针、auto变量等。
3.C语言有一些不安全的语言特性。如指针使用的潜在危险、强制转换的不确定性、内存泄漏等。C++对此增加了不少新特性来改善安全性,如const常量、引用、cast转换、智能指针 try-catch等。
4.C++可复用性高,C++引入模板概念、后面在此基础上实现了方便开发的标准模板库STL。C++的STL相对于C语言库更灵活更通用。
2、说说C++中struct和class的区别
1.struct一般描述一个数据结构集合,而class是对一个数据对象的封装
2.struct中默认的访问控制权限是public的,而class中默认的访问控制权限是private
3.在继承关系中,struct默认是公有继承,而class是私有继承
4.class关键字可以用于定义模板参数,就像typename,而struct不能定义于模板参数
3、简述C++从代码到可执行二进制文件的过程
C++从源码到可执行文件,有四个过程预编译、编译、汇编、链接
1.预编译
(1)将所有的#define删除,并展开宏定义
(2)处理所有的条件预编译指令,如#if、#ifdef
(3)处理#include预编译指令,将被包含的文件插入到该预编译指令的位置
(4)过滤掉所有注释
(5)添加行号和文件名标识
2.编译
(1)词法分析:将源代码的字符序列分割成一系列的记号
(2)语法分析:对记号进行语法分析,产生语法树
(3)语义分析:判断表达式是否有意义。
(4)代码优化:
(5)目标代码生成:生成汇编代码。
(6)目标代码优化:
3.汇编
这个过程主要是将汇编代码转换成机器可以执行的指令
4.链接
1.将不同的源文件产生的目标文件进行链接,从而形成一个可执行的程序
链接分为静态链接和动态链接。
静态链接,是在链接的时候就已经把要调用的函数或者过程链接到了生成的可执行文件中,就算你在去把静态库删除也不会影响可执行程序的执行;生成的静态链接库,Windows下以.lib为后缀,Linux下以.a为后缀。
而动态链接,是在链接的时候没有把调用的函数代码链接进去,而是在执行的过程中,再去找要链接的函数,生成的可执行文件中没有函数代码,只包含函数的重定位信息,所以当你删除动态库时,可执行程序就不能运行。生成的动态链接库,Windows下以.dll为后缀,Linux下以.so为后缀。
5、说说内联函数和宏函数的区别
宏定义不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率;而内联函数本质上是一个函数,内联函数一般用于函数体的代码比较简单的函数,不能包含复杂的控制语句,while、switch,并且内联函数本身不能直接调用自身。
宏函数是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换 ;而内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的开销,提高效率
宏定义是没有类型检查的,无论对还是错都是直接替换;而内联函数在编译的时候会进行类型的检查,内联函数满足函数的性质,比如有返回值、参数列表等
6、 说说new和malloc的区别,各自底层实现原理。
参考回答
new是操作符,而malloc是函数。
new在调用的时候先分配内存,在调用构造函数,释放的时候调用析构函数;而malloc没有构造函数和析构函数。
malloc需要给定申请内存的大小,返回的指针需要强转;new会调用构造函数,不用指定内存的大小,返回指针不用强转。
new可以被重载;malloc不行
new分配内存更直接和安全。
new发生错误抛出异常,malloc返回null
答案解析
malloc底层实现:当开辟的空间小于 128K 时,调用 brk()函数;当开辟的空间大于 128K 时,调用mmap()。malloc采用的是内存池的管理方式,以减少内存碎片。先申请大块内存作为堆区,然后将堆区分为多个内存块。当用户申请内存时,直接从堆区分配一块合适的空闲快。采用隐式链表将所有空闲块,每一个空闲块记录了一个未分配的、连续的内存地址。
new底层实现:关键字new在调用构造函数的时候实际上进行了如下的几个步骤:
创建一个新的对象
将构造函数的作用域赋值给这个新的对象(因此this指向了这个新的对象)
执行构造函数中的代码(为这个新对象添加属性)
返回新对象
6、说说什么是野指针,怎么产生的,如何避免?
**概念:**野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
**产生原因:**释放内存后指针不及时置空(野指针),依然指向了该内存,那么可能出现非法访问的错误。这些我们都要注意避免。
避免办法:
(1)初始化置NULL
(2)申请内存后判空
(3)指针释放后置NULL
(4)使用智能指针
答案解析
产生原因:释放内存后指针不及时置空(野指针),依然指向了该内存,那么可能出现非法访问的错误。这些我们都要注意避
8、简述C++有几种传值方式,之间的区别是什么?
传参方式有这三种:值传递、引用传递、指针传递
值传递:形参即使在函数体内值发生变化,也不会影响实参的值;
引用传递:形参在函数体内值发生变化,会影响实参的值;
指针传递:在指针指向没有发生改变的前提下,形参在函数体内值发生变化,会影响实参的值;
答案解析
值传递用于对象时,整个对象会拷贝一个副本,这样效率低;而引用传递用于对象时,不发生拷贝行为,只是绑定对象,更高效;指针传递同理,但不如引用传递安全。
9、 说说内联函数和宏函数的区别
区别:
宏定义不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率;而内联函数本质上是一个函数,内联函数一般用于函数体的代码比较简单的函数,不能包含复杂的控制语句,while、switch,并且内联函数本身不能直接调用自身。
宏函数是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换 ;而内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的开销,提高效率
宏定义是没有类型检查的,无论对还是错都是直接替换;而内联函数在编译的时候会进行类型的检查,内联函数满足函数的性质,比如有返回值、参数列表等
10、 说说内联函数和函数的区别,内联函数的作用。
内联函数比普通函数多了关键字inline
内联函数避免了函数调用的开销;普通函数有调用的开销
普通函数在被调用的时候,需要寻址(函数入口地址);内联函数不需要寻址。
内联函数有一定的限制,内联函数体要求代码简单,不能包含复杂的结构控制语句;普通函数没有这个要求。
内联函数的作用:内联函数在调用时,是将调用表达式用内联函数体来替换。避免函数调用的开销。
答案解析
在使用内联函数时,应注意如下几点:
在内联函数内不允许用循环语句和开关语句。 如果内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码,递归函数是不能被用来做内联函数的。内联函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。
内联函数的定义必须出现在内联函数第一次被调用之前。