文章标题

来源:互联网 发布:网络诈骗的案例 编辑:程序博客网 时间:2024/06/16 06:56

算法基础

主要记录笔试中相关算法与程序

[Num_001] C++中的inline关键字

1、关于c++的inline关键字,以下说法正确的是(D)A、使用inline关键字的函数会被编译器在调用处展开B、头文件中可以包含inline函数的声明C、可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数D、定义在Class声明内的成员函数默认是inline函数E、优先使用Class声明内定义的inline函数F、优先使用Class实现的内inline函数的实现

1、什么是内联函数?

在C语言中,如果一些函数被频繁调用,不断地有函数入栈,即函数栈,会造成栈空间或栈内存的大量消耗。为了解决这个问题,特别的引入了inline修饰符,表示为内联函数。

栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。

栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足所造成的程式出错的问题,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

2、inline的使用限制

inline的使用是有所限制的,inline只适合函数体内代码简单的函数使用不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)

3、inline仅是一个对编译器的建议

inline函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。

4、建议:inline函数的定义放在头文件中

因为内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,要不然就成了非内联函数的调用了。所以,这要求每个调用了内联函数的文件都出现了该内联函数的定义

因此,将内联函数的定义放在头文件里实现是合适的,省却为每个文件实现一次的麻烦。

此外,声明跟定义要一致:如果在每个文件里都实现一次该内联函数的话,那么,最好保证每个定义都是一样的,否则,将会引起未定义的行为。如果不是每个文件里的定义都一样,那么,编译器展开的是哪一个,那要看具体的编译器而定。所以,最好将内联函数定义放在头文件中

5、类中的成员函数与inline

定义在类中的成员函数缺省都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上inline,否则就认为不是内联的。

6、inline 是一种“用于实现的关键字”

关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

inline void Foo(int x, int y); // inline 仅与函数声明放在一起void Foo(int x, int y){}
void Foo(int x, int y);inline void Foo(int x, int y) {} // inline 与函数定义体放在一起

7、慎用inline

内联能提高函数的执行效率,为什么不把所有的函数都定义成内联函数?如果所有的函数都是内联函数,还用得着“内联”这个关键字吗?
内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

以下情况不宜使用内联:
(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。

[Num_002] 数组排序算法复杂度

数组排序算法

[Num_003] TCP/IP

2、在TCP/IP建立连接过程中,客户端和服务器端的状态转移说法错误的是(D)A、经历SYN_RECV状态B、经历SYN_SEND状态C、经历ESTABLISHED状态D、经历TIME_WAIT状态E、服务器在收到syn包时将加入半连接队列F、服务器接受到客户端的ack包后将从半连接队列删除

TCP三次握手与四次挥手

在可靠的TCP网络通信中,客户端和服务器端通信建立连接的过程可简单表述为三次握手(建立连接的阶段)和四次挥手(释放连接阶段),

TCP协议三次握手过程分析
TCP(Transmission Control Protocol) 传输控制协议
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:

位码即tcp标志位,有6种标示:
SYN(synchronous建立联机)、
ACK(acknowledgement 确认)、
PSH(push传送)、
FIN(finish结束)、
RST(reset重置)、
URG(urgent紧急)

Sequence number(顺序号码)
Acknowledge number(确认号码)

第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

完成三次握手,主机A与主机B开始传送数据。


在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据.

三次握手与四次挥手的状态转移图如下:
这里写图片描述

[Num_003]

如下C程序,在64位处理器上运行后size的值是什么?

struct st{    int *p;    int i;    char a;};int sz=sizeof(struct st);

考点:
1.struct的对齐原则,注意不同的编译器有不同的效果。
2。不同的数据类型在32位和64位下所占字节的区别
32位编译器
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节

Bit 类型 字节Byte 32 char 1 32 char* 4 32 short int 2 32 int 4 32 unsigned int 4 32 float 4 32 double 8 32 long 4 32 long long 8 32 unsigned long 4 64 char 1 64 char* 8 64 short int 2 64 int 4 64 unsigned int 4 64 float 4 64 double 8 64 long 8 64 long long 8 64 unsigned long 8

[Num_004] 类的静态成员

下面关于一个类的静态成员描述中,不正确的是(C)A、静态成员变量可被该类的所有方法访问B、该类的静态方法只能访问该类的静态成员函数C、该类的静态数据成员变量的值不可修改D、子类可以访问父类的静态成员E、静态成员无多态特性

类的静态成员属于整个类 而不是某个对象,可以被类的所有方法访问,子类当然可以父类静态成员;
静态方法属于整个类,在对象创建之前就已经分配空间;
类的非静态成员要在对象创建后才有内存;
所有静态方法只能访问静态成员,不能访问非静态成员;
静态成员可以被任一对象修改,修改后的值可以被所有对象共享。没有多态性

A
A
A
A
A
A
A
A

原创粉丝点击