1、C和C++的区别
? ? ? ? 1)编程范式(c:面向过程 c++: 面向对象)
? ? ? ? 2)?动态内存分配(c: malloc/free c++:new/delete)
? ? ? ? 3)c++支持函数重载
? ? ? ? 4)c++支持模板
? ? ? ? 5)c++除了指针还支持引用(引用的本质是常指针)
? ? ? ? 可以回答的内容很多,以上作为参考,还有其他不同地方可继续总结!
2、C++文件编译与执行的四个阶段
????????1)预处理:根据文件中的预处理指令来修改源文件的内容
????????2)编译:编译成汇编代码????????
????????3)汇编:把汇编代码翻译成目标机器指令
????????4)链接:链接目标代码生成可执行程序
3、?定义和声明的区别
声明是告诉编译器变量的类型和名字,不会为变量分配空间
定义需要分配空间,同一个变量可以被声明多次,但是只能被定义一次
4、C++的内存管理
在C++中,内存被分成五个区:栈、堆、自由存储区、静态存储区、常量区
栈:存放函数的参数和局部变量,编译器自动分配和释放
堆:new关键字动态分配的内存,由程序员手动进行释放,否则程序结束后,由操作系统自动进行回收
自由存储区:由malloc分配的内存,和堆十分相似,由对应的free进行释放
全局/静态存储区:存放全局变量和静态变量
常量区:存放常量,不允许被修改
5、extern“C”作用
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。也就是C和C++代码的编译逻辑是不一样的,并且C中的全局变量也需要被其他引用的文件识别。
6、?static 的作用域
?某一个文件中定义的静态的变量,则它的作用域是整个文件。与之相对的的是extern!
在.h文件中定义了一个静态的全局变量x,不同文件为每个包含该头文件的cpp都创建一个全局变量,但他们都是独立的,只在该cpp文件共享该变量。所以一般定义static全局变量时,都把它放在cpp文件中而不是头文件,从而避免多个源文件共享,从而造成不必要的信息污染。
7、enum枚举类型和#define宏定义的区别
- 宏定义没有类型检查和安全检查,所以会导致边际效应,出现不可预知的错误;enum在编译阶段进行类型检查,但是只能进行整型的定义
- 宏定义仅仅是替换和展开,并不进行内存的分配;enum常量存储在内存数据段的静态存储区
- define是在预处理阶段对所定义的常量进行替换展开;enum是程序运行时起作用
- 枚举常量具有类型,但宏没有类型
8、栈溢出的原因以及解决方法
1)函数调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈
2)局部变量体积太大。
解决办法大致说来也有两种:
1)增加栈内存的数目;增加栈内存方法如下,在vc6种依次选择Project->Setting->Link,在Category中选择output,在Reserve中输入16进制的栈内存大小如:0x10000000
2)使用堆内存;具体实现由很多种方法可以直接把数组定义改成指针,然后动态申请内存;也可以把局部变量变成全局变量,一个偷懒的办法是直接在定义前边加个static,呵呵,直接变成静态变量(实质就是全局变量)
9、 C++中const的作用以及和宏的区别
????????const修饰的内容不可改变, 定义常量只是一种使用方式,还有const数据成员,const参数, const返回值, const成员函数等, 被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
? ? ? ? const相对#define可以做类型校验,并且分配内存。
10、 既然C++中有更好的const为什么还要使用宏
????????宏的作用发生在预编译,const是再编译阶段,所以const无法代替宏作为卫哨来防止文件的重复包含。
?11、new/delete 与 malloc/free的区别?
?malloc与free是C语言的标准库函数, new/delete是C++的运算符, 他们都可以用来申请和释放内存, malloc和free不在编译器控制权限之内, 无法调用构造函数和析构函数;而new/delete是由C++编译器控制的,可以在分配内存之外调用构造函数和析构函数。
?12、RTTI
typeid 和 dynamic_cast
具体原理可以参考:C++类型预断——RTTI_master-计算机科学专栏-CSDN博客
13、 四种类型转换
(1)static_cast:用于良性转换,一般不会导致意外发生,风险很低。常用于基本类型转换到 void,转换父类指针到子类不安全 。
(2)const_cast:一般用于去掉const属性以及volatile,但是如果原来他就是常量去掉之后千万不要修改;比如你手里有一个常量指针引用,但是函数接口是非常量指针,可能需要转换一下;成员函数声明为const,你想用this去执行一个函数,也需要用const_cast.
(3)dynamic_cast:用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。
(4)reinterpret_cast:非常简单粗暴,所以风险很高,一般用于跨类型的转换,如int到void*,用于序列化网络包数据等。
?14、STL由什么组成
????????由容器,迭代器,仿函数,算法,分配器,适配器构成。分配器给容器分配存储空间,算法通过迭代器获取容器中的内容,仿函数可以协助算法完成各种操作,配置器用来套接适配仿函数。
15、?什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?
动态分配内存所开辟的空间,在使用完毕后未释放,导致一直占据该内存,即为内存泄漏。
避免内存泄漏方法:
- ?谁开辟谁释放????????
- ?使用智能指针? ? ? ? ?
- ?指针指向新地址时参考规则1
- ?new和delete、new[]和delete[]要对应
?16、阐述C++的多态
多态是指一个接口多种实现,这是面向对象编程的核心,多态分为以下两种:
静态多态:也就是编译时多态,主要实现方式为重载、模板
动态多态:也就是运行时多态,主要实现方式为虚函数 + 继承
17、new与new[] delete与delete[]的区别?
请参考 :深入理解new[]和delete[]_master-计算机科学专栏-CSDN博客
18、动态多态的实现原理
动态多态的实现是借助虚函数表来实现的,具体实现还要看一下C++的内存模型和C++的虚函数表的实现。(这里就不做过多讲解,如果不懂的,可以回看老师的课程视频)
19、inline函数能否是virtual函数
????????不可以,inline只是一个申请,最终由编译器决定内联还是不内联。如果inline函数被声明为virtual函数,编译器此时不会认为这是一个内联函数。为什么?因为inline是发生在编译阶段,而virtual是运行阶段的!
? ? ? ? 总之,要virtual就不要inline,要inline就不要virtual!
20、引用是否能实现动态绑定,为什么引用可以实现
????????可以。因为引用(或指针)既可以指向基类对象也可以指向派生类对象,这一事实是动态绑定的关键。用引用(或指针)调用的虚函数在运行时确定,被调用的函数是引用(或指针)所指的对象的实际类型所定义的。
? ? ? ? 换句话说,引用的本质是常量指针,指针指向的对象当然可以在运行阶段来实现动态调用。
|