1.extern关键字的作用是什么?
声明外部成员函数、成员数据
extern关键字可以用来声明变量、函数作为外部变量或者函数供其它文件使用。
2.关于virtual void Draw()=0
纯虚函数是在声明虚函数时被“初始化”为0的函数。声明纯虚函数的一般形式是
virtual 函数类型 函数名 (参数表列) =0;
注意: ①纯虚函数没有函数体;②最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”; ③这是一个声明语句,最后应有分号。
纯虚函数只有函数的名字而不具备函数的功能,不能被调用。它只是通知编译系统: “在这里声明一个虚函数,留待派生类中定义”。在派生类中对此函数提供定义后,它才能具备函数的功能,可被调用。
3.对于类的常成员函数
成员函数是指在函数定义的末尾加一个const. 如:
void A (int x ) const
{
return x;
}
1.它表示这个函数内的代码不会改变传入参数的值,方便了程序员阅读代码和减少bug
2.当一个对象为const时,只有常成员函数才能调用它,没有定义const的函数会有改变其值的嫌疑,故不能成功编译。
如:
class Set
{
Add(){} ;
Show() const{};
}
const Set s;
s.Add(10); // 非法: s.Add(10)不是常量成员函数 s.Show(10)才是;
4.Class A{ Chara; Public: A():a(0){} A(charaa) {//把aa所指字符串拷贝到a所指向的存储空间 A=***new char[strlen(aa)+1]***; Strcpy(a,aa);} ~A(){delete [] a;} };
字符串最后需要有个自动添加的’\0’作为结束标志,所以+1
5.无条件转移指令功能是将指令中的地址码送入
直接寻址是指操作数存放在内存单元中,指令中直接给出操作数所在存储单元的地址。而跳转指令中的操作数即为要转向执行的指令地址,因此,应将指令中的地址码送入程序计数器(PC),以获得下一条指令的地址,从而实现程序执行过程的自动控制功能。
6.C/C++的编译包括几个部分
预处理:gcc -E project.c -o project.i //宏展开,宏替换
编译:gcc -S project.i -o project.s //将目标文件编译成汇编文件
汇编:gcc -c project.s -o project.o //汇编成二进制文件
链接:gcc project.o -o project //加载库文件,生成可执行文件
1、预编译:预处理器对c程序进行一些预处理工作,例如对宏定义的变量进行替换;
1)将所有的#define删除,并展开所有的宏定义;
2)处理所有的预编译指令,例如:#if,#elif,#else,#endif;
3)处理#include预编译指令,将被包含的文件插入到预编译指令的位置;
4)添加行号信息文件名信息,便于调试;
5)删除所有的注释:// /**/;
6)保留所有的#pragma编译指令,因为在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作;
最后生成.i文件;
总的来说,包括(1)去注释 (2)宏替换 (3)头文件展开 (4)条件编译
2、编译:编译器将c语言程序翻译成汇编语言程序;
1)扫描,语法分析,语义分析,源代码优化,目标代码生成,目标代码优化;
2)生成汇编代码;
3)汇总符号;
4)生成.s文件;
3、汇编:汇编语言通过汇编器编译成可重定位目标程序.o,与之相反称为反汇编;
1)根据汇编指令和特定平台,把汇编指令翻译成二进制形式;
2)合并各个section,合并符号表;
3)生成.o文件;
4、链接:将目标文件和所需的库函数用链接器进行链接,常见的链接器有Unix;
1)合并各个.obj文件的section,合并符号表,进行符号解析;
2)符号地址重定位;
3)生成可执行文件
7.
#include <iostream>
using namespace std;
int function(int x)
{
int flag = 0;
while (x)
{
x = x & (x - 1);
flag++;
}
return flag;
}
int main(void)
{
cout << function(9561) << endl;
return 0;
}
7
8.
#include <iostream>
using namespace std;
typedef union {
short i;
int k[5];//20
char c;
} Mat;
typedef struct {
int i;//4
Mat j;
double k;//8
}Like;
int main(void)
{
cout << 4+20+8+20 << endl;
cout << sizeof(Like) + sizeof(Mat) << endl;
return 0;
}
52
9.某关键词用于声明敏感变量(默认其他线程随时可以改变其值,因此每次运算都会读取新的值,避免误读缓存数据引发的错误)
volatile
10.RAW型依赖关系?
a = b + c;
d = a + c;
RAW(read after write): 写后读关系
先写a,之后再在d=a+c时读a
11.对于乱序执行的处理器,下列哪个流水线阶段是乱序执行的
指令执行
乱序执行(out-of-order execution)是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理的技术。比方Core乱序执行引擎说程序某一段有7条指令,此时CPU将根据各单元电路的空闲状态和各指令能否提前执行的具体情况分析后,将能提前执行的指令立即发送给相应电路执行。
12.关于NUMA架构
一颗CPU修改了共享的内存位置,需要广播给所有其他CPU。
非统一内存访问架构(英语:Non-uniform memory access,简称NUMA)是一种为多处理器的计算机设计的内存架构,内存访问时间取决于内存相对于处理器的位置。在NUMA下,处理器访问它自己的本地内存的速度比非本地内存(内存位于另一个处理器,或者是处理器之间共享的内存)快一些。
非统一内存访问架构的特点是:被共享的内存物理上是分布式的,所有这些内存的集合就是全局地址空间。所以处理器访问这些内存的时间是不一样的,显然访问本地内存的速度要比访问全局共享内存或远程访问外地内存要快些。另外,NUMA中内存可能是分层的:本地内存,群内共享内存,全局共享内存。
13.关于this指针使用说法
保证基类公有成员在子类中可以被访问
this指针是一个隐含指针,它隐含于每个类的非静态成员函数中。this指针是成员函数所属的对象指针,它指向当前类的对象地址。通过this指针访问当前对象成员有两种方式:(*this).成员,this->成员。
14.程序的局部变量存在于1中,全局变量存在于2中,动态申请数据存在于3中,变量放在堆区与栈区的区别是4。
(1) 栈
(2) 静态区
(3) 堆
(4) 从申请方式,申请大小,申请效率简单比较:Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。Stack空间有限,Heap是很大的自由存储区。Stack申请效率高,Heap申请效率低。
15.请写一个严谨的宏”MAX”,返回两个参数中较大的一个
#define MAX(A,B) ((A)>(B)?(A):(B))
16.如何防止头文件被重复引用
#ifndef/#define/#endif
17.若一组记录的排序码为(32, 1, 52, 25, 88, 56),则利用快排的方法从小到大排序,以第一个记录为基准得到的一次划分结果为
以32为基准,第一次1比32小——>(1, 32, 52, 25, 88, 56)
第二次52大于32的不动——>(1, 32, 52, 25, 88, 56)
第三次25小于32——>(25,1, 32, 52, 88, 56)
后面都比32大,所以第一轮排序完就是25,1, 32, 52, 88, 56