82道linux下c-c++语法知识点归纳和总结面试题

2019-07-3114:10:50编程语言入门到精通Comments2,783 views字数 16216阅读模式
82道linux下c-c++语法知识点归纳和总结面试题

1、c/c++申请动态内存

在c++中,申请动态内存是使用new和delete,这两个关键字实际上是运算符,并不是函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

而在c中,申请动态内存则是使用malloc和free,这两个函数是c的标准库函数,使用它们必须包含stdlib.h,才能编译通过。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

new/delete和malloc/free的相同之处在于,new和malloc都是手动申请动态内存,释放时new则需要delete释放内存,而malloc则需要free释放内存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

它们的不同之处在于,new和delete会自动调用对象的构造和析构函数,而malloc/free则只申请内存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

另外需要注意的是:new的不是数组的话,则直接delete就好,并且只会调用一次析构函数,而new[]的话,则需使用delete[]来释放,并且数组中每一个元素都会调用一次析构函数,调用完析构函数再释放内存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

2、c++继承的优缺点

优点:类继承是在编译时刻静态定义的,且类继承可以较方便地改变父类的实现,实现函数的重用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

缺点:首先,因为继承在编译时刻就定义了,所以无法在运行时改变从父类继承的实现,其次,父类一般至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为,也就是说,如果继承下来的实现不适合子类的问题,那么父类必须重写或者被其他的类替换,这种依赖关系限制了灵活性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

从以上对比看,同一种属性既可以是优点,从另外的方面来讲,又是缺点,就看个人在编程过程中的灵活运用了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

3、c++的三大特性

封装、继承、多态。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

封装是一种技术,它使类的定义和实现分离;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

继承,从广义上讲,继承有三种实现方式,其一,为实现继承,指使用基类的属性和方法而无需额外编码,其二,可视继承,即子窗体使用父窗体的外观和实现代码,其三,则为接口继承,即仅仅继承属性和方法,实现则滞后到子类去实现,也就是父类使用的是纯虚函数,或者重写父类接口方法,则是虚函数,例如多态的实现就使用了接口继承。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

多态,简单来讲,就是父类定义了虚函数,子类重新实现该函数,那么当父类指针指向子类时,会调用子类的该方法,这,就是多态。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

4、子类和父类调用构造函数和析构函数的先后顺序

子类对象定义时,先调用父类的构造函数,再调用子类的构造函数;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

子类对象销毁时,先调用子类的析构函数,再调用父类的析构函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

5、什么是引用

引用,其实就是给变量取了一个别名,声明引用时要切记初始化,且引用本身不占存储单元,纯粹就是变量多了一个名称而已。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

6、将引用作为函数参数有哪些特点

一是,使用引用传递参数是直接对实参本身进行操作,当需要在函数内部修改传递进来的变量并传出去时,可使用引用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

二是,作为函数参数时,引用是无需重新分配存储空间的,那时引用只是作为别名使用,但指针却需要,所以有时使用引用会更有效率;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

7、什么时候需要使用常引用

当既要使用引用提高程序的效率,又不能在函数内部修改实参的值时,可使用常引用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

8、将引用作为函数返回值类型的好处和需遵循的规则

好处:在内存中不产生被返回值的副本文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

需遵循的规则:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(1)不能返回局部变量的引用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)不能返回函数内部动态分配的变量的引用,因为引用只是作为一个临时变量的出现,并未赋予一个实际的变量,该引用所指向的空间无法被释放;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(3)可以返回类成员的引用,但最好是const类型;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(4)为了保证连续使用流操作符(<< >>)重载返回值时,操作的是同一个对象,流操作符重载返回值应该声明为引用文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(5)+-*/这四则运算符不能返回引用文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

9、引用和多态的关系

引用是c++中另外一种实现多态的手段,与指针一样,也是基类的引用可指向派生类的实例。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

10、引用和指针的区别

指针通过某个指针变量指向某个对象后,对指针所指向的对象间接操作;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

引用本身就是变量的别名,所以对引用操作就是直接对所指向的变量进行操作;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

引用不会重新分配存储空间,但指针却需要重新分配存储空间;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

11、关联、聚合、组合的区别

主要是在画uml类图时,有关联、聚合和组合的说法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

关联,是一种很弱的联系,指的是两个类之间有某种联系,比如一个类实例作为另一个类方法的参数;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

聚合,指的是整体与部分的关系。通常在定义一个整体类后,再去分析这个整体类的组成结构。从而找出一些组成类,该整体类和组成类之间就形成了聚合关系。例如一个航母编队包括海空母舰、驱护舰艇、舰载飞机及核动力攻击潜艇等。需求描述中“包含”、“组成”、“分为…部分”等词常意味着聚合关系;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

组合,也表示类之间整理和部分的关系,但是组合关系中部分和整体具有统一的生存期,一旦整体对象不存在,部分对象也将不存在;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

聚合和组合的区别:就是聚合关系中部分事物和整体事物生存期无关,举个浅显的例子,国和家,国没了,家也就不存在了,这是组合关系,而计算机和它的外设之间,计算机没了,硬件设备还存在,这是聚合关系。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

12、多态(也叫重写和覆盖)的作用

隐藏实现细节,使得代码能够模块化,进而扩展代码模块,实现代码的重用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

在继承的同时,每一个派生类都有属于自己的独特的方法,实现接口的重用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

13、什么情况下只能使用类构造函数初始化表而不能赋值

当类中含有const、reference(引用)成员变量时,类的构造函数都需要初始化表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

14、c++是否是类型安全的

不是,c++是可以进行强制类型转换的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

15、main函数执行以前会执行什么代码

全局对象的构造函数会在main函数之前执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

16、描述内存分配方式以及它们的区别

一是从静态存储区域分配,内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如全局变量和static变量;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

二是从栈上创建,一般是局部变量在栈上创建,当超过该变量的作用域时该变量被自动释放;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

三是从堆上手动分配,一般动态分配内存都是在堆上创建。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

17、struct和class的区别

struct的成员默认是公有的,class的成员默认是私有的;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

当类中有很少的方法并且有公有数据时,应该使用struct关键字,否则使用class关键字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

18、在8086汇编下,逻辑地址和物理地址是怎样转换的

通用寄存器给出的地址,是段内编译地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

19、请说出const和#define相比,有什么优点

const常量有数据类型,而宏定义没有数据类型;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

部分调试工具可以对const进行调试,但是宏常量不行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

20、简述数组和指针的区别

数组要么在静态存储区创建,要么在栈上创建,指针可以随时指向任意类型的内存:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  1. 修改内容上的差别:

char a[] = “hello”;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

a[0] = ‘X’;//正确,编译和运行都不报错文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

char *p = “hello”;//注意p指向常量字符串文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

p[0] = ‘X’;//不正确,编译不报错,运行时报错文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)sizeof计算容量时,数组得出字节数,指针则是4个字节文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

21、类成员函数的重载、覆盖和隐藏的区别

重载即为函数重载,重载的特征:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(1)相同的范围,也就是在同一个类中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)函数名字相同文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(3)参数不同文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(4)virtual关键字无影响文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

覆盖是指派生类函数覆盖基类函数,覆盖的特征:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(1)不同的范围,即函数分别位于派生类和基类文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)函数名字相同文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(3)参数相同文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(4)基类函数必须有virtual关键字文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

隐藏是指派生类的函数屏蔽了与其同名的基类函数,特征如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(1)如果派生类的函数与基类的函数同名,但是参数不同,此时不论有没有virtual关键字,基类的函数都将被隐藏文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)如果派生类的函数与基类的函数同名,参数也相同,但是基类函数没有virtual关键字,此时,基类的函数将被隐藏文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

总结:函数名相同,参数也相同的情况下,如果基类函数有virtual关键字,则是多态,否则就是隐藏;函数名相同,参数不同的情况下,如果函数位于同一个类中,则是重载,否则就是隐藏。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

22、main主函数执行完毕后,是否可能会再执行一段代码

atexit函数,是注册终止函数,即main执行结束后调用的函数,注册以后函数将由exit函数自动调用,其中atexit注册的函数类型应该是不接受任何参数的void函数,exit调用这些注册函数的顺序与它们登记时候的顺序相反。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

另外,atexit函数是包含在stdlib.h库中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

23、代码中特殊的注释技术-TODO, FIXME 和 XXX

TODO:如果代码中有该标识,说明在标识处有功能代码待编写, 待实现的功能在说明中会简略说明;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

FIXME:如果代码中有该标识,说明标识处代码需要修正,甚至代码是错误的,不能工作,需要修复,如何修正会在说明中简略说明;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

XXX:如果代码中有该标识,说明标识处代码虽然实现了功能,但是实现的方法有待商榷,希望将来能改进,要改进的地方会在说明中简略说明。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

24、代码中连用两个感叹号

c代码中连用两个感叹号表示非非,如果是0,那么还是0,如果原来是非0,则变为1.文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

25、友元类的说明

友元关系不能被继承,友元关系是单向的,友元关系不具有传递性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

26、多态的内部逻辑

(1)从包含虚函数的类派生一个类时,编译器就为该类创建一个VTABLE,其每一个表项是该类的虚函数地址;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(2)在定义该派生类对象时,先调用其基类的构造函数,然后再初始化VPTR,最后再调用派生类的构造函数(从二进制的视野来看,所谓基类子类是一个大结构体,其中this指针开头的四个字节存放虚函数表头指针,执行子类的构造函数的时候,首先调用基类构造函数,this指针作为参数,在基类的构造函数中填入基类的vptr,然后回到子类的构造函数,填入子类的vptr,覆盖基类填入的vptr,如此一来完成vptr的初始化)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

(3)在实现动态绑定,不能直接采用类对象,而一定要采用指针或者引用,因为采用类对象传值方式,有临时基类对象的产生,而采用指针,则是通过指针来访问外部的派生类对象的vptr来达到访问派生类虚函数的结果。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

27、虚析构函数的作用

只有当一个类被用作基类时才需要使用虚析构函数,这样做的作用是当一个基类的指针删除派生类的对象时,能确保派生类的析构函数会被调用。因为编译器它只知道基类指针,调用基类析构,并不会主动去调用派生类的析构函数,所以基类析构函数需为虚析构函数,这就相当于析构函数的多态。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

28、#ifndef 和 #pragma once的区别

#ifndef是手动定义宏名来避免冲突,但#pragma once是编译器提供保证。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#ifndef是依赖于宏的名字不能起冲突,可以保证同一个文件不会被包含多次,但缺点是如果不同头文件的宏名不小心撞车了,可能就会导致头文件命名存在,但编译器却报找不到声明的情况。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#pragma once由编译器自动提供保障,同一个物理上的文件不会被包含多次,就是内容相同,但只要是两个文件,都会分别包含,但如果一个头文件被拷贝了多份,这种方法就不能保证文件不被重复包含。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#ifndef语法移植性好,#pragma once可以避免名字冲突。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

29、__declspec(dllexcept) 和 __declspec(dllimport)

#ifdef ASIMOVLIB_EXPORTS文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#define ASIMOVLIB_API __declspec(dllexport)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#else文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#define ASIMOVLIB_API __declspec(dllimport)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#endif文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

__declspec(dllexport):文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话, 你无法在DEF里指定导出的函数,只能用dllexport导出类。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

__declspec(dllimport):文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

声明一个导入函数,是说这个函数是从别的dll导入,我要用,一般用于使用某个dll的exe中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

不适用__declspec(dllimport)也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。但是,必须使用__declspec(import)才能导入DLL中使用的变量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

30、explicit关键字的作用

explicit用来防止由构造函数定义的隐式转换,比如:class Base base=10;即Base类只有一个int类型的变量,explicit使用了以后,就不允许这样写。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

被声明为explicit的构造函数通常比非explicit的构造函数更受欢迎,因为它们禁止编译器执行非预期的类型转换。除非我有个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

31、printf输出时在%和字母之间插入数字表示场宽的规则?

当实际长度不够时, 右对齐;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

如果字符串或者整数的长度超过说明的场宽, 则按其实际长度输出;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

如果是浮点数, 若整数部分超过了说明的整数位场宽, 则按其实际长度输出, 若是小数部分超过了说明的小数位场宽, 则按说明的宽度以四舍五入输出。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

32、逗号表达式?

例如:printf(“%d %d %d\n”, (a,b,c),b,c);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

那么将输出才c,b,c这3个值,因为逗号表达式的值就是表达式中最后一个表达式的值;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

即:表达式1,表达式2,表达式3…表达式n 就是表达式n的值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

33、c语言中标识符第一次字符必须是什么?

第一个字符必须是字母或者下划线,不能是数字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

34、数据流程图(DFD图)是什么

DFD图是结构化方法的需求分析工具。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

35、hash_set和set的区别?

hast_set以hashtable为底层机制,而set以RB-tree(红黑果树)为底层机制;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

set有元素自动排序功能,而hash_set没有;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

set可在logN下完成查找、插入和删除等操作,hash_set可在常数时间复杂度下完成这些操作,但是取决于哈希表的负载情况;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

hast_multiset则允许键值重复;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

36、static的用途以及类中使用static的规则。

用途:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

static限制变量的作用域;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

static不显示的初始化时,会被隐式的初始化为0;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

static设置变量的存储域,变量存储在静态区;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类中使用static的规则:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

不能通过类名来调用类的非静态成员函数,可以调用静态成员函数;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类的对象可以使用静态成员函数和非静态成员函数;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类的静态成员函数中不能使用类的非静态成员,因为此时静态成员函数已经分配了存储空间,而非静态成员却还没有分配内存,相当于变量声明了但是未定义就直接使用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类的非静态成员函数(包括常函数)可以使用类的静态成员函数和静态成员变量,并且非静态成员常函数可以修改静态成员变量;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类的静态成员变量必须初始化以后才能使用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

37、数据库三范式

  • 第一范式:数据库表中的所有字段值都是不可分解的原子值,比如地址字段,根据需求拆分成省份和城市更方便
  • 第二范式:在一个数据库表中,一个表中只能保持一种数据,不可以把多种数据保存在同一张数据库表中,比如订单信息和商品信息就要分为两个表
  • 第三范式:每一列数据都和主键直接相关,而不能间接相关,就是说字段值要和主键有直接关系

巴斯-科德范式:第三范式的一个子集,在第一范式基础上,任何非主属性不能对主键子集依赖。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

38、网络编程中设计并发服务器,使用多进程和多线程,请问有什么区别?

1)两者都可以提高程序的并发度,提高程序运行效率和响应时间文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

2)线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

39、可以用作switch的参数的类型

int、short、byte、char、long文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

基本上可以转换为整数的类型都可以用作switch的参数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

40、linux使用多线程的方法

互斥锁、信号量、条件变量、全局变量、读写锁。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  1. 互斥锁:当线程A锁定了互斥变量时,线程B再去锁定时就会被挂起,直到A解锁。

注意:当线程要不断的去轮询检查某个条件以判断是否可以操作需同步的数据时,可使用条件变量提高效率。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  1. 信号量:就是一个整数,两个线程对整数进行加减来实现信号量。
  2. 条件变量:经常和互斥锁一起使用,使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程会解开相应的互斥锁并等待条件发生变化,一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此变量阻塞的线程,这些线程将重新锁定互斥锁并重新测试条件是否满足。

pthread_cont_init()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_cont_destroy()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_cont_wait() //线程解开mutex指向的锁并被条件变量阻塞文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_cont_timedwait() //多了时间参数,当时间过了以后,即使条件变量不满足,阻塞也被解除文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_cont_signal()/pthread_cont_broadcast //唤醒被条件变量阻塞的线程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  1. 读写锁:可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。
  • 当读写锁是写加锁状态时,在这个锁被解锁前,所有试图对这个锁加锁的线程都会被阻塞;
  • 当读写锁是读加锁状态时,其他线程可以读模式得到访问权,但是以写模式对它进行加锁的线程都将被阻塞;
  • 当读写锁是在读模式加锁状态时,如果有其他线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,避免读模式锁长期占用,而写模式所长期阻塞;

读写锁适用于对数据读的次数比写的次数多的情况。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

API接口:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

初始化和销毁:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int pthread_rwlock_init();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int pthread rwlock_destroy();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

读加锁、写加锁、解锁:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_rwlock_rdlock();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_rwlock_wrlock();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_rwlock_unlock();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

非阻塞获得读锁和写锁:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_rwlock_tryrdlock();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

pthread_rwlock_trywrlock();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

41、linux系统进程间通信方式

管道、有名管道、信号量、消息队列、信号、共享内存、socket、文件文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

管道及有名管道:管道可用于具有亲缘关系进程间的通信,例如父子进程,但是有名管道允许无关系的进程间通信。管道其实就是建立一个FIFO文件,一个进程往里面写数据,另外的进程读取数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

信号量:主要作为进程间以及同一进程不同线程之间的同步手段。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

消息队列:也叫报文队列,消息队列是消息的链接表,包括Posix消息队列和SystemV消息队列,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的信息,消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

信号:信号是比较复杂的通信方式,用于通知接收进程有某种事情发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信息语义函数signal外,还支持语义符合Posix 1标准的信号函数sigaction。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

共享内存:共享内存是一种文件映射,使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其他通信机制,如信号量结合使用,来达到进程间的同步及互斥。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

socket:也就是套接字,最普遍的进程间通信机制,可用于不同机器之间的进程间通信。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

42、为什么要使用linux作为服务器。

首先,linux是免费的,而windows需要向微软购买正版授权;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

其次,linux比windows灵活,可以实现很多定制化需求,因为linux可以修改系统内核;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

再次,很多高端服务器组件对linux支持的更好,windows版本的可能功能都不是很完整;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

最后,linux开源,所以很多人为它添砖加瓦,几乎你需要的功能都能找到linux的版本并且都是开源免费的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

43、mysql数据库的引擎

你能用的数据库引擎取决于mysql在安装的时候是如何被编译的。要添加一个新的引擎,就必须重新编译mysql,在缺省情况下,mysql支持三个引擎:ISAM、MYISAM和HEAP,另外两种类型INNODB和BERKLEY,也常常可以使用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

ISAM文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

ISAM是一个定义明确且历经时间考验的数据库表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。ISAM的两个主要不足之处在于,它不支持事务处理,也不能够容错,如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把ISAM用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,Mysql能够支持这样的备份应用程序。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

MYISAM文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

MYISAM是MySQL的ISAM扩展格式和缺省的数据库引擎,除了提供ISAM里所没有的索引和字段管理的大量功能,MYISAM还使用一种表格锁定的机制,来优化多个并发的读写操作。其代价是你需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的时间。MYISAM还有一些有用的扩展,例如用来修复数据库文件的MYISAMCHK工具和用来恢复浪费空间的MYISAMPACK工具。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

MYISAM强调了快速读取操作,这可能就是为什么MYSQL受到了WEB开发如此青睐的主要原因,在WEB开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和INTERNET平台提供商只允许使用MYISAM格式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

HEAP文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

HEAP允许只驻留在内存里的临时表格。驻留在内存使得HEAP比ISAM和MYISAM的速度都快,但是它所管理的数据是不稳定的,而且如果在关机之前没有进行保存,那么所有的数据都会丢失。在数据行被删除的时候,HEAP也不会浪费大量的空间,HEAP表格在你需要使用SELECT表达式来选择和操控数据的时候非常有用。要记住,用完表格后要删除表格。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

INNODB和BERKLEYDB文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

INNODB和BERKLEYDB数据库引擎都是造就MYSQL的灵活性技术的直接产品,这项技术就是mysql++API。在使用mysql的时候,你所面对的每一个挑战几乎都源于ISAM和MYISAM数据库引擎不支持事务处理也不支持外来键。尽管要比ISAM和MYISAM引擎慢很多,但是INNODB和BERKLEYDB包括了对事务处理和外来键的支持,这两点都是前两个引擎所没有的。如前所述,如果你的设计需要这些特性中的一者或者两者,那你就要被迫使用后两个引擎中的一个了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

44、什么是红黑数?

红黑树,又叫RB树,是一种特殊的二叉查找树,可以自动排序,且红黑树的每个节点都有存储位表示节点的颜色,标识是红或者黑。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

红黑树的特性:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

每个节点或者是黑色,或者是红色;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

跟节点是黑色;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

每个叶子节点是黑色(这里叶子节点是指没有子节点的叶子节点);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

如果一个节点是红色的,则它的子节点必为黑色的;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

从一个节点到该节点子孙节点的所有路径上包含相同数目的黑节点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

45、C程序的内存分配方式

由上到下(地址从高到低):栈、动态链接库、堆、bbs(未初始化的全局变量)、数据段(存放初始化的全局变量)、文本段(存放代码)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

46、select、poll、epoll的区别

select函数 int select(int n,fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第一个参数n代表最大的文件描述符+1文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

fd_set是一个集合,存放的是文件描述符文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

readfds表示我们要监视这些文件描述符里读变化文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

writefds表示我们要监视它所指向的集合里面的文件描述符的写变化文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

errorfds表示要监视文件描述符是否发生了错误异常文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

timeout若为NULL,则select置于阻塞状态,直到监视的某个文件描述符发生变化才返回文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

timeout若等于0秒0毫秒,则select是一个纯粹的非阻塞函数,不管文件描述符是否变化,立即返回。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

timeout大于0时,则在timeout时间内阻塞,timeout时间内若文件描述符有变化则返回,如果超时则立即返回文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

返回值:负值 select发生错误文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

正值 有文件描述符发生变化文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

0 等待超时,没有可读写或者发生错误的文件描述符文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

poll文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

poll使用pollfd结构文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

epoll函数与select函数最大的不同在于它不会随着监听fd数目的增长而降低效率,并且select同时监听的fd数目是有限制的,默认最大是1024.文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int epoll_create(int size);//创建epoll句柄,参数size告诉内核这个监听的数目有多大,但最新版本这个参数已经无用了文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int epoll_ctl(); //epoll的事件注册函数,它要先注册需要监听的事件类型文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int epoll_wait();//等待事件的发生文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

select是轮询fd,而epoll是先将文件描述符注册到内核,一旦文件描述符发生变化,内核会采用回调机制,激活这个文件描述符,这样epoll_wait便会知道。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

epoll相对于select有点:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  • 监视的文件描述符不受限制,具体多少根内存有关
  • IO的效率不会随着监视fd的数量的增加而降低
  • mmap加速内核与用户空间的信息传递,避免了多余的内存拷贝

47、linux下inode的说明

每个磁盘空间都有一个inode表,inode里面每一个节点存放该空间每个文件的信息,例如:文件的字节数、文件拥有者、所在的组、权限、时间、位置等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

istat 命令查看单个文件;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

df –i查看磁盘空间inode的使用量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

48、IP、TCP、UDP数据包大小

MTU,普通局域网最大传输单元,为1500个字节;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

IP数据包首部20个字节,所以IP数据包一般是1480个字节;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

TCP数据包首部20个字节,所以数据包大小为1460个字节;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

UDP数据包首部8个字节,所以数据包大小我1472个字节;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

注意:这里说的首部是固定长度,但后面还有一些可选字段。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

49、memcache的特性

  • 服务器接到客户端请求会先检查memcached,如有则直接返回,不再检查DB
  • 如memcache没有要找的数据,则检查DB,查到以后返回给客户端,并同时缓冲一份到memcache
  • 更新DB同时更新memcache,保证数据的一致性
  • 当分配给memcache内存空间用完之后,会根据LRU(最近最少使用)策略和到期失效策略,先替换失效数据,再替换最近最少使用数据
  • memchche在内存中是一个巨大的hast表,它其实就是读数据库改为直接读内存,提高读取速度

50、什么是sql注入

sql注入:用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

应对办法:可以通过数据库防火墙实现对sql注入攻击的防范,因为sql注入攻击往往是通过应用程序来进攻,可以使用虚拟补丁技术实现,对注入攻击的sql特征识别,实现实时攻击阻断。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

51、对称加密算法和非对称加密算法

对称加密才用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥,即加密密钥也可以用解密密钥,这就是对称加密算法,常见的有:DES、IDEA。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

非对称加密算法需要两个密钥:公开密钥和私有密钥,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;反之,则用对应的公开密钥解密。非对称加密不适合对文件加密,只适合对少量数据进行加密,典型的应用是数字签名。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

52、volatile关键字的作用

volatile变量是随时可能发生变化的,它告诉编译器,与volatile变量有关的运算,不要进行任何优化,每次读取volatile变量时都重新从内存读取。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

53、c++中动态联编和静态联编

静态联编说的是在编译时就已经确定好了调用和被调用两者的关系;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

动态联编说的是程序在运行时才确定调用者和被调用者的关系,典型的应用是虚函数实现的多态性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

54、深拷贝和浅拷贝

浅拷贝是指将对象内的数据完全一致的复制;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

深拷贝不是这样,它可以将内部的数据按照需要用特殊的方法拷贝,比如说对象内部有一个动态数组,浅拷贝只拷贝指针,而深拷贝则重新申请空间将数据复制过来。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

55、什么是柔性数组?

数组大小待定的数组就是柔性数组。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

一般结构体的最后一个元素可以是大小未知的数组。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

56、库函数和系统调用的区别?

库函数调用时面向应用开发的,与系统无关,移植性好。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

系统调用是面向底层,偏向硬件,系统内核软中断实现,移植性差。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

系统调用是用户程序和内核交互的接口,系统调用的过程如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  • 执行用户程序
  • 根据glibc的函数实现,取得系统调用号,并执行int$0x80产生中断
  • 进行地址空间的转换和堆栈的切换,执行SAVE _ALL(进入内核模式)
  • 进行中断处理,根据系统调用表调用内核函数
  • 执行内核函数
  • 执行RESTORE_ALL并返回用户模式

系统调用比库函数调用快。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

57、构造函数里面”初始化列表”和”赋值”的区别

对于内置类型来说,没有区别,对于非内置类型则有区别,如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

初始化列表只会调用一次构造函数,而赋值会先调用构造,再调用一次赋值函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

什么情况下只能使用初始化列表:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

没有默认构造函数的类;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

类中存在const成员或者引用类型的成员(它们只能被初始化);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

58、为什么要字节对齐?

自然对齐:一个变量的内存正好是它长度的整数倍。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

需要字节对齐的根本原因在于CPU的效率问题,假设32位机器上int型变量地址是0x00000002,那么CPU取值时需要访问两次内存,一次是0x00000002-0x00000003的short,然后是0x00000004-0x00000005的short,而如果该int型变量的地址是0x00000003,那么CPU则要访问3次内存,即char-short-char,而如果变量是自然对齐的,则CPU访问一次内存就够了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

struct stu文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

{文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

char sex;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int length;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

char name[10];文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

};文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

sizeof(struct stu) = 20;//结构体中每个数据类型都要对齐文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

什么情况下需要手动设置对齐:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  1. 设计不同CPU下的通信协议(设计一个结构体,32位和64位都用时)
  2. 编写硬件驱动程序时寄存器的结构

手动设置对齐方式有两种:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

1)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#pragma pack(n)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

#pragma pack()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

2)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

GNU编译时 #define GNUC_PACKED__attribut__((packed))文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

59、浅谈僵尸进程

僵尸进程:当子进程退出时,父进程没有调用wait函数或者waitpid()函数等待子进程结束,又没有显式忽略SIGCHLD信号,那么它将一直保持在僵尸状态,如果这时父进程结束了,init进程会自动接收这个子进程,为它收尸,但如果父进程是一个循环,不会结束,那么子进程就会一直保持僵死状态。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

进程状态:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

僵尸文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

休眠文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

不可中断的休眠文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

运行文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

停止式跟踪文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

Z文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

S文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

D文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

R文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

T文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

补救办法:杀死僵尸进程的父进程,让init进程来接手,清理掉子进程这个僵尸进程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

僵尸进程的状态:一个进程在调用exit()函数结束时,并没有真正的被销毁,而是留下一个称为僵尸进程的数据结构,僵尸进程放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保持一个位置,记载该进程的退出状态等信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

避免僵尸进程的方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  • 使用signal函数忽略SIGCHLD信号
  • 调用wait或者waitpid()函数
  • fork两次,父进程fork子进程后继续执行,子进程fork一个孙进程后退出,此时孙进程会被init进程接管,避免僵尸进程,当然子进程的退出还是要进行处理的。

60、fork函数浅析

pid_t fork();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程的进程id,否则,出错返回-1.文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

注意:子进程拥有的是副本,它跟父进程之间是不共享这些存储空间(但是共享代码段)的,因此子进程拥有独立的地址空间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

fork可能出错的原因:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

当前进程数量已经达到了系统规定的上限;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

系统内存不足;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

61、for_each的用法?

for_each是C++STL中用来遍历容器的函数模板,有3个参数:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第一个是容器开始,例如:map.begin()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第二个是容器结束,例如:map.end();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第三个是operator(),仿函数,函数对象文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

当第三个函数有其他参数时,与bind1st和bind2nd一起使用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

void record(const int &n)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

{文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

cout << n << endl;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

int num [5] = {1,2,3,4,5};文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

for_each(num,num+sizeof(num)/sizeof(num[0]),record);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

62、什么是事务以及事务包含哪些属性?

事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是不可分割的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

sql语言中,定义事务的语句有3条:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

begin transaction;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

… //这里嵌入sql语句文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

commit transaction;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

rollback transaction;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

事务的4个属性:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

  • 原子性:事务中的所有元素作为一个整体提交或回答,事务的每个元素是不可分的,事务是一个完整操作
  • 一致性:事务完成时,数据必须是一致的,也就是不能破坏数据
  • 隔离性:事务允许多个用户对同一个数据进行并发访问,而不破坏数据的完整性和正确性。同时,并行事务的修改必须与其他并行事务的修改相独立
  • 持久性:事务结束后,事务处理的结果必须能够得到固化

63、c++强制转换

const_cast 用于去除const属性文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

static_cast 用于基本类型的强制转换文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

dynamic_cast 用于多态类型之间的类型转换文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

reinterpreter_cast 用于不同类型指针之间的转换,最常用的就是不同类型之间函数指针的转换文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

64、linux手动的让内核崩溃

cd /proc/sys/kernel文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

echo 1 > sysrq文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

cd /proc文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

echo c > sysrq-trigger文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

65、mutable关键字

mutable加在类型前面,表示即使是常量也可以修改文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

66、带外数据

OOB数据,也叫带外数据,send/sendto发送数据时以MSG_OOB标记。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

带外数据只支持tcp,不支持udp文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

带外数据发送时不优先,接收时优先;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

接收带外数据的系统会发送一个SIGURG信号文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

67、自定义类型作为map键时需注意什么?

  1. 重载 “<” 操作符,因为需要自动排序
  2. 无法重载时,用自定义仿函数代替map第三个参数

map 第一个参数是key文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第二个参数是value文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第三个参数是compare比较函数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

第四个参数是内存配置对象文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

68、虚基类的用法

虚继承+多重继承时防止二义性问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

从类A派生出B和C,类D又继承自B和C,此时类D的对象就包含了两个类A的对象,这样类D调用类A的成员变量和成员函数时就会产生二义性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

解决办法:B虚继承A,C也虚继承A,此时就不会再有二义性了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

69、析构函数能否为虚函数,为什么?什么情况下析构函数一定要是虚函数。

析构函数可以是虚函数,因为它是对象结束时才调用,不影响虚表构建。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

构造函数不能是虚函数,因为调用构造函数时,虚表才建立。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

当类有派生类时,析构函数要是虚函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

删除指向派生类的基类指针时,只会删除基类对象,而不删除子类对象,造成内存泄露。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

公有继承时,基类对派生类和对象的操作,只能影响那些继承下来的成员,如果要对非继承成员,例如子类析构函数进行操作,则这个函数必须定义为虚函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

70、怎样防止类对象被拷贝和赋值?

  • 拷贝构造函数和赋值函数定义为私有的
  • 私有继承基类

71、能不能从构造函数调用虚函数,为什么?

可以的,只是虚函数会使用基类的虚函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

72、什么时候可能会出现这种情况?设定的断点在main()函数的第一行,但是程序运行后没有执行到断点就崩溃退出了?

全局变量的构造函数崩溃。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

73、如何处理一个析构函数失败,可以抛出一个异常?

最好不要抛出,如果一定要抛出,那要在析构函数内部处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

74、如何处理构造函数失败?

抛出异常,若有动态分配内存,则要在抛异常之前手动释放。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

75、friend违反封装原则了吗,为什么?

违反了,友元函数可以不受访问权限的限制而访问类的任何成员。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

76、脏数据是怎么发生的?

数据被删除,但另一用户没有刷新,使用了该数据,这就是脏数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

77、什么是模板的特例化?

模板的特例化是指将typename指定类型用一个已知类型替代了,用已知类型重新实现了模板函数和类,如果模板有2个参数,只实例化了一个参数,则是偏特化(局部特化)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

78、STL仿函数需要重载哪个操作符?

operator(),仿函数是指可以“使用小括号传递参数,来调用某个东西”。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

79、c++中前置操作符和后置操作符有什么区别?哪个效率更高?

前置是先将自身改变再参与表达式运算,可以当作左值使用;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

后置是先参与表达式计算再改变自身的值,返回的是右值,不能当作左值使用(i++=6 错误),前置效率高,因为后置会产生临时对象。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

80、fork后父子进程的内存布局

调用fork之后,系统会为子进程建立父进程的副本,即子进程获得父进程数据空间、堆、栈的副本,父子进程之间并不共享这些存储空间部分,但父进程和子进程会共享正文段。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

而因为现在fork以后通常会执行exec函数,所以现在一开始的时候子进程并没有完全获得父进程的存储空间的副本,作为替代,使用了"写时复制"技术,即这些区域开始由父进程和子进程共享,而且内核将它们的访问权限改为只读,如果父进程和子进程任一个试图修改这些区域,则内核会为修改区域的那块内存制作一个副本,通常是虚拟存储系统中的一个页。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

调用fork()之后先执行哪个进程的是由Linux下专有文件/proc/sys/kernel/sched_child_runs_first的值来确定的(值为0父进程先执行,非0子进程先执行)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

81、unix中c程序的存储空间布局

c程序的存储空间通常由以下几部分组成:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

1.正文段,也就是代码段,是由cpu执行的机器指令部分,正文段在存储器中只会有一个副本,并且正文段常常是只读的,以防止程序由于意外而修改其指令。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

2.初始化数据段,也称为数据段,它包含了程序中需明确赋初值的变量(通常是函数外有初值的变量)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

3.未初始化数据段,也称为bbs段,在程序开始执行之前,内核将此段中的数据初始化为0或者空指针(通常是函数外没有初值的变量)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

4.栈。局部变量以及每次函数调用时所需保存的信息都存放在栈中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

5.堆。通常在此段中进行动态存储分配,一般来说,堆位于bbs段和栈之间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

程序执行以后才会产生堆和栈。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

内核执行程序都会调用exec函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

典型的程序逻辑布局:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

地址从低到高:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

正文段--》初始化数据段--》未初始化数据段--》堆--》栈文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

堆顶和栈顶之间会有很大的一段未使用的虚地址空间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

82、同步IO和异步IO

cpu执行的速度远远高于磁盘读写速度或者是网络传输速度,当代码执行遇到磁盘读写的时候,当前线程就会一直等待,直到磁盘读写完成返回后再继续执行下面的代码,这样就造成了cpu的资源严重浪费。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

为了解决这种情况,我们可以使用多线程和多进程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

但是多进程开多了的话是很占用系统资源的,而多线程也是不能一直增加的,因为cpu要在线程之间切换来切换去,也是很耗费时间和资源的,这种情况下,我们可以使用异步IO。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

异步IO,就是说当执行某段耗时的代码时,只发出指令,并不等待执行结果,然后就去执行其他代码,一段时间后,当结果返回时,再通知cpu进行处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

那么根据上面的描述来讲,同步是阻塞的,异步是非阻塞的,异步IO需要一个消息循环,在消息循环中,主线程不断地重复读取消息,处理消息这一过程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

也就是说,在发出IO请求到IO返回结果的这一段时间里,同步IO模式下,主线程只能挂起等待,而异步IO模式下,主线程会继续去处理下一个消息,这样既没有占用过多的资源,也无需在线程之间进行切换,就会大大提升多任务处理程序的性能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

其实消息循环并不是说跳过io读写往下执行,而是不在等待,接着执行下一次循环,当IO读写完成后再接着往后执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/14775.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/14775.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定