C/C++知识总结(1)

1.malloc、free和new、delete的区别

  • Malloc和free是c的库函数,new和delete是c++的操作符;
  • New会自动计算所需分配空间大小,malloc需要手动计算空间;
  • New分配失败会抛出异常,malloc分配失败返回的是NULL
  • New是在自由存储区上分配内存,malloc在堆上分配;
  • Delete需要对象类型的指针,freevoid*类型的指针。
  • 被free回收的内存首先会被ptmalloc使用双链表保存起来,当用户下次申请时候,会从这里面寻找合适的内存返回。同时ptmalloc也会对较小的内存进行合并,这样就避免了过多的内存碎片。

2.静态库与动态库的区别

  • 静态库是在程序编译时便链接进程序当中,而动态库在编译链接时只保留了可执行文件对库的引用,即只保留了接口;
  • 静态库由于在编译时便打包进文件中,因此占用空间大,而动态库只是保留了接口,因此占用空间小;
  • 静态库适用于独立可移植的程序,动态库可以独立更新并被多个程序共享;
  • 静态库函数调用是直接调用,效率更快,动态库函数调用需要经过中间层,调用效率更慢。

3.常见进程调度算法

  • 先来先服务调度算法(FCFS
  • 短作业优先调度算法(SJF
  • 优先级调度算法
  • 时间片轮转调度算法
  • 多级反馈队列调度算法:动态调整进程优先级和时间片大小

4.孤儿进程与僵尸进程

  • 对于一般进程来说,由父进程创建子进程,子进程再创建新的进程;父子进程是异步过程,父进程无法预测子进程的结束。所以子进程结束后,父进程会通过wait()或者waitpid()来获取子进程的终止状态,回收掉子进程的资源。
  • 孤儿进程:父进程结束了,但是子进程还在运行,这些子进程就是孤儿进程。孤儿进程的资源由init进程(进程号pid=1)回收。
  • 僵尸进程:子进程退出了,但是父进程没有用wait或者waitpid去获取子进程的状态信息,那么子进程的进程描述仍然保持在系统中。
  • 任何一个子进程在推出后,都会留下一个称为僵尸进程的数据结构,如果父进程没有及时处理,那么僵尸进程就会一直占用子进程原来的资源。
  • 孤儿进程没有任何危害,僵尸进程如果大量存在,就会导致无法产生新的进程。

5.TCP与UDP的区别

  • UDP是面向无连接的,TCP是面向连接的,因此UDP减小了开销和发送前的时延。
  • UDP使用最大努力的交付,TCP提供可靠交付的服务,TCP使用的是停止等待协议。
  • UDP是面向报文的,对应用程序交来的报文添加首部后便直接交给下一层IP层。
  • UDP没有拥塞控制,因此网络出现拥塞时不会使得主机发送速率降低。
  • TCP提供全双工通信方式,TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据;应用程序将数据放在缓存区,并在合适的时候从缓存区读走数据。

6.进程的5种基本状态与转换

  • 创建,就绪,阻塞,运行,终止。

7.进程与线程的区别

  • 进程是系统对资源分配和调度的基本单位,线程是CPU执行与调度的基本单位。
  • 进程有自己的独立地址空间与资源,线程共享进程的地址空间与资源。
  • 一个程序至少有一个进程,一个进程至少有一个线程;一个进程崩溃后,通常不会对其他进程造成影响,而一个线程崩溃后,通常会导致整个进程都死掉,因此多进程要比多线程健壮。

8.不同类型所占字节

byte : 1  short : 2  int : 4  long : 8  float : 4  double : 8  char : 2  bool : JVW规范中,bool当int处理,所以占4字节;但如果是bool数组,则当成byte处理,所以每个元素占1字节。

9.结构体内存对齐

结构体内成员按照声明顺序存储,第一个成员地址和整个结构体地址相同。

未经特殊说明时候,按结构体size最大的成员对齐。

alignas可以指定结构体对齐方式,但是若指定的size小于自然对齐的最小单位,则失效。

alignof可以计算对齐的大小。

10.指针

int *p = &a;//表示p指针存储变量a所在的地址

指针的const限定:在指针前面加const,表示不能通过指针来改变指向的const对象的值。(可以给指针赋值,即地址,但是不能通过*引用运算符去改变这个地址里面的值)

把const的对象的地址赋值给非const对象的指针是错误的,但是把非const对象的地址赋给const对象的指针是可以的

 int * p;  

 int a[10];

 p = a;//a代表整个数组,将a数组的首地址赋给p        a+1表示数组第二个元素地址,若a是二维数组,则是下一个子维度的地址

 p = &a;//将整个a数组的地址赋给p,即a[0]~a[9]  &a+1表示跳过整个数组的下一个对象的地址

 p = &a[0];//将a的首地址赋给p          &a[0]+1和a+1一样

int *p[10];//定义了一个指针数组,这个数组里面每个元素都是一个指向int型的指针,数组大小是10;

int (*p)[10];//定义了数组指针,这个指针指向一个int型大小为10的数组;

int *p(int);//定义了一个指针函数,函数名叫做p,形参是int类型,返回值是int *类型的;

int (*p)(int);//定义了一个函数指针,这个指针指向一个传递int型参数的函数,且这个函数返回值是int类型的。

11.指针与引用的区别

指针是一个变量,存储的是它所指向对象的地址,而引用和原来的变量实质上是一个东西,只不过是别名。

指针不需要初始化,可以为空,但引用必须初始化且不能为空。

指针在初始化后可以改变指向,但是引用在初始化后不能改变指向。

12.在函数传递参数时,什么时候使用引用,什么时候使用指针

需要返回函数内局部变量的内存时候使用指针;

对栈空间比较敏感的函数,比如递归函数,使用引用传递;

类对象作为参数传递时候使用引用。

13.C++内存概念

C++内存分为5个区:堆,栈,自由存储区,全局/静态存储区和常量存储区

栈:通常时局部变量或者函数参数等,创建时候会分配栈里面的空间,不需要的时候会自动清除内存。

堆:通常使用new分配内存块,使用完后需要手动delete,否则交给操作系统去回收。堆里面的变量都没有名字,都是通过指针访问,堆里面生成变量的过程叫做动态内存分配。

自由存储区:由malloc分配的内存块,需要手动free结束生命。

全局/静态存储区:顾名思义,全局变量和静态变量分配到这里面。

常量存储区:存储常量。

内存泄漏:用动态存储(new,malloc)开辟出来的空间在使用后没有释放掉,就会一直占用该存储单元。如果程序一直运行下去,可能会导致死机。

14.宏定义与函数的区别

宏在预处理阶段完成替换,之后被替代的文本区参加编译;函数则是在运行时候跳转到具体的调用函数。

宏定义的参数没有类型,不会进行类型检查;函数定义的参数有类型,需要进行参数检查。

15.strlen和sizeof的区别

sizeof是运算符,结果在编译时得到;strlen是库函数,结果在运行时得到。

sizeof的参数可以是任何数据类型,返回数据类型的大小;而strlen的参数只能是以‘\0’结尾的字符串,返回字符串长度。

sizeof的值是编译时得到的,不能计算动态分配得到的空间大小。

posted on 2024-03-23 16:03  xy-struggle  阅读(26)  评论(0)    收藏  举报

导航