c++ 常见知识点

1.const 含义是什么?

const关键字至少有下列n个作用:

(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。

2.malloc,vmalloc,kmalloc 的区别是什么,及其分别的作用?

1、kmalloc()
kmalloc()函数类似与我们常见的malloc()函数,前者用于内核态的内存分配,后者用于用户态。
kmalloc()函数在物理内存中分配一块连续的存储空间,且和malloc()函数一样,不会清除里面的原始数据,如果内存充足,它的分配速度很快。
2.vmalloc()
vmalloc()一般用在为只存在于软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存,当内存没有足够大的连续物理空间可以分配时,可以用该函数来分配虚拟地址连续但物理地址不连续的内存。由于需要建立新的页表,所以它的开销要远远大于kmalloc及后面将要讲到的__get_free_pages()函数。且vmalloc()不能用在原子上下文中,因为它的内部实现使用了标志为 GFP_KERNEL 的kmalloc()。
3.malloc()
当我们需要做一个成绩管理系统,人数可能为全校学生,也可能为一个班的学生,当我们开辟一个班的数组大小时,如果要存储整个学校的人数时,会出现内存不够用的情况;当我们开辟全校人数大小的数组时,输入一个班人数的大小时,会出现内存浪费的情况。
为了应对上述问题,我们引入malloc函数。
malloc时动态内存分配函数,用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址

3.C++ 中对new申请的内存的释放方式有delete和delete[]两种方式,到底这两者有什么区别呢?

delete 释放new分配的单个对象指针指向的内存;

delete[] 释放new分配的对象数组指针指向的内存。

  1. 针对简单类型 使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可 如:

int *a = new int[10];
delete a;
delete[] a;

  1. 针对类Class,两种方式体现出具体差异

当你通过下列方式分配一个类对象数组:
class A
{
private:
char *m_cBuffer;
int m_nLen;
`` public:
A(){ m_cBuffer = new char[m_nLen]; }
~A() { delete [] m_cBuffer; }
};
A *a = new A[10];
delete a; //仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户自行分配的m_cBuffer对应内存空间将不能释放 从而造成内存泄漏
delete[] a; //调用使用类对象的析构函数释放用户自己分配内存空间并且 释放了a指针指向的全部内存空间

4.中断处理函数

一、什么是中断服务函数
在单片机中,中断服务函数(Interrupt Service Routine,简称ISR)是用于响应硬件中断的函数。单片机是一种集成了处理器、内存、I/O接口等组件的微型计算机,它通常用于嵌入式系统中。当单片机的硬件设备发生特定的事件或条件时(例如外部触发、定时器到期等),会产生一个硬件中断信号,处理器会根据中断向量表中的配置,跳转到相应的中断服务函数去处理这个中断事件。

    在单片机中,中断服务函数通常是由程序员编写的,用于处理外部事件和优化系统性能。由于单片机的资源有限,中断服务函数的编写通常需要精心设计,以确保在最短的时间内完成必要的处理,使系统能够快速恢复正常运行。

二、结论
在大多数单片机中,中断服务函数是不带形参和返回值的。因为中断处理是异步的,中断发生时通常会中断当前执行的任务,直接跳转到中断服务函数执行,没有办法传递参数给中断服务函数。同样,由于中断处理是在中断上下文中进行的,没有合适的方法来返回处理结果。
虽然在大多数单片机中,中断服务函数不带形参和返回值,但编程时可以使用全局变量或共享的数据结构来在中断服务函数中访问外部信息和传递数据。
需要注意的是,中断服务函数在执行时必须尽可能地快速,因为在中断处理期间,主程序暂停执行,其他中断也可能被屏蔽,如果中断服务函数执行时间过长,可能导致系统响应缓慢或不稳定。

5.boolalpha函数

boolalpha的作用是使bool型变量按照false、true的格式输出

6.PID和TID
PID和TID之间的区别
疑问:
标准答案是PID用于进程,而TID用于线程。但是,我已经看到一些命令可以相互使用它们。
例如,htop有一个PID列,其中显示了相同进程的线程的PID(具有不同的值)。
那么PID什么时候代表线程或进程?

解释
首先:pid是进程标识符; tid是线程标识符。
但实际上,内核并没有真正区分它们:线程和进程很像,但它与同一组的线程共享一些东西(内存,fds …)。
因此,tid实际上是内核(线程)中可调度对象的标识符,而pid是共享内存和fds(进程)的可调度对象组的标识符。
但是有趣的是,当一个进程只有一个线程时,pid和tid总是相同的。因此,任何与tid一起使用的函数都将自动使用pid。

首先我们从操作系统原理,即从理论上讲,进程是任务的资源分配单位,而线程是任务的执行单位。每个进程都是由一个或多个线程组成的。

而PID是进程的全局唯一ID,TID是线程的全局唯一ID。没有问题!

Linux内核
但是原理和实现是不一样的,操作系统原理这本书,其实是对各种操作系统实现的抽象和总结,那么Linux中是如何实现的呢?

我相信你应该知道,在Linux中线程其实是通过轻量级进程实现的,也就是LWP(light weight process),因此在Linux中每个线程都是一个进程,都拥有一个PID,换句话说,操作系统原理中的线程,对应的其实是Linux中的进程(即LWP),因此Linux内核中的PID对应的其实是原理中的TID。

操作系统原理中的进程对应谁呢?其实是Linux中的线程组,准确的叫法应该是轻量级进程组,但是由于Linux中轻量级进程就是线程,所以一般叫做Linux线程组,同一Linux线程组的线程(LWP),是共享内存地址空间的,即共享页表。而Linux线程组中的主线程的PID,在数值上等于该线程组的TGID,这个TGID对应了原理中的PID。

6.LUR算法

我们接触过Redis时,会不会想过如果当前内存已经占满,那么我们在由其他的数据要写入Reids时,这时候Redis会怎么做呢?这就是要设计到Redis 的淘汰机制:

1.noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)

2.allkeys-lru:从所有key中使用LRU算法进行淘汰

3.volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰

4.allkeys-random:从所有key中随机淘汰数据

5.volatile-random:从设置了过期时间的key中随机淘汰

6.volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰

淘汰策略通常利用LUR 算法,大致意思就是不常用的数据优先淘汰,释放当前数据的内存,将新的数据放入内存中;

7.自动变量

在C语言中,变量有三种类型:自动变量(automatic variable)、静态变量(static variable)和寄存器变量(register variable),他们大部分地方都是相似的,但是每个都有各自的特性。

自动变量(automatic variable):
这是最常用的变量,声明和初始化格式类似int a = 0;。如果不初始化,它的值是未定义的初始值。每次函数调用的时候,也就是重新进入该变量的作用域的时候,变量会重新初始化。而且自动变量的初始化并不被限定为常数,而是可以包含任何式子——先前定义的值,甚至是调用函数。此外,自动变量的名称可以和外部变量或者函数的名称重复,这时候会隐藏外部变量或者函数(不推荐重复名称来使用,这样会导致混乱或者恶性bug)。

静态变量(static variable):
静态变量和自动变量很像,声明和初始化的格式类似static int a = 0;。如果不初始化,它的值是0。不同之处是它的值是永久存储的,而不会随着函数再次调用而再次初始化;而且静态变量初始化必须是一个常数式。

寄存器变量(register variable):
这种变量一般用于程序中某个变量被重度使用,为了提升性能。声明格式类似register int a;。如果不初始化,它的值是未定义的初始值。而且寄存器变量和自动变量一样,初始化并不被限定为常数,而是可以包含任何式子:先前定义的值,甚至是调用函数。如果使用这种类型的变量,会将变量放入寄存器中,由于存储层级关系,这样会提升性能。但是受限于基础设备限制,只有少数变量能被放入寄存器,放不下全部的。并且需要注意的是:1. register声明只能声明自动变量和函数的参数。2. 编译器可以自由忽略我们标注的register,只将其当作自动变量来处理。3. 无法获取寄存器中变量的地址。4. 寄存器变量的数字和类型的限制取决于机器。

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值