131、static_cast比C语言中的转换强在哪里?
- 更加安全;
- 更直接明显,能够一眼看出是什么类型转换为什么类型,容易找出程序中的错误;
- 可清楚地辨别代码中每个显式的强制转换;
- 可读性更好,能体现程序员的意图;
132、成员函数里memset(this,0,sizeof(*this))会发生什么?
背景:
- 有时候类里面定义了很多int,char,struct等c语言里的那些类型的变量,我习惯在构造函数中将它们初始化为0,但是一句句的写太麻烦;
- 所以直接就
memset(this, 0, sizeof *this);将整个对象的内存全部置为0。对于这种情形可以很好的工作。
但是下面几种情形是不可以这么使用的:
- 类含有虚函数表;这么做会破坏虚函数表,后续对虚函数的调用都将出现异常;
- 类中含有C++类型的对象; 例如,类中定义了一个list的对象,由于在构造函数体的代码执行之前就对list对象完成了初始化,假设list在它的构造函数里分配了内存,那么我们这么一做就破坏了list对象的内存。
133、你知道回调函数吗?它的作用?
- 当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数;
- 回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用;
- 为此,你需要做三件事:1,声明;2,定义;3,设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用;
- 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数;
- 因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
134、hello.c 程序的编译过程
以下是一个 hello.c 程序:
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
在 Unix 系统上,由编译器把源文件转换为目标文件。
gcc -o hello hello.c
这个过程大致如下:

预处理阶段: 处理以 # 开头的预处理命令;
编译阶段: 翻译成汇编文件;
汇编阶段: 将汇编文件翻译成可重定位目标文件;
链接阶段: 将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。
静态链接:
- 静态链接器以一组可重定位目标文件为输入,生成一个完全链接的可执行目标文件作为输出。
链接器主要完成以下两个任务:
- 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
- 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。

目标文件:
- 可执行目标文件:可以直接在内存中执行;
- 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件;
- 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接;
动态链接
静态库有以下两个问题:
- 当静态库更新时那么整个程序都要重新进行链接;
- 对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。
共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。
它具有以下特点:
- 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
- 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。

源代码-->预处理-->编译-->优化-->汇编-->链接–>可执行文件
1、预处理
- 读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理。
- 包括宏定义替换、条件编译指令、头文件包含指令、特殊符号。
- 预编译程序所完成的基本上是对源程序的“替代”工作。
- 经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。
-.i预处理后的c文件,.ii预处理后的C++文件。
2、编译阶段
- 编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
.s文件。
3、汇编过程
- 汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。
- 目标文件中所存放的也就是与源程序等效的目标的机器语言代码。
.o目标文件
4、链接阶段
- 链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来;
- 使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。
135、为什么不能把所有的函数写成内联函数?
- 内联函数以代码复杂为代价,它以省去函数调用的开销来提高执行效率;
- 一方面如果内联函数体内代码执行时间相比函数调用开销较大,则没有太大的意义;
- 另一方面每一处内联函数的调用都要复制代码,消耗更多的内存空间。
因此以下情况不宜使用内联函数:
- 函数体内的代码比较长,将导致内存消耗代价;
- 函数体内有循环,函数执行时间要比函数调用开销大。
136、为什么C++没有垃圾回收机制?这点跟Java不太一样。
- 首先,实现一个垃圾回收器会带来额外的空间和时间开销。你需要开辟一定的空间保存指针的引用计数和对他们进行标记mark。然后需要单独开辟一个线程在空闲的时候进行free操作。
- 垃圾回收会使得C++不适合进行很多底层的操作。
1084

被折叠的 条评论
为什么被折叠?



