- 前言
- 一、C++相关
- 1.dynamic_cast的实现机制
- 2.函数重载的底层原理?为什么C++可以重载?
- 3.原始指针、unique_ptr和shared_ptr的使用场景
- 4.C和C++的适用性和场合?C++面向对象好在哪里?为什么嵌入式用C多?
- 5.share_ptr 直接类构造和用 make_shared 区别?
- 6.POSIX C相关
- 7.static_cast 和 reinterpret_cast 的区别?
- 8.模板在哪个阶段进行处理?
- 9.private继承有什么用?在什么场景下使用?
- 二、操作系统
- 1.共享内存怎么实现?
- 2.生产者消费者模式
- 3 有哪些锁?介绍它们的实现?
- 4.单核CPU使用多线程是否能提高效率?
- 5.Linux查看进程内存占用
- 6.条件变量的作用、使用场景?
- 7.系统调用是通过什么机制陷入内核的?
- 8.open与fopen的区别是什么?
- 三、计算机网络
- 1. 为什么有了流量控制还要有拥塞控制?
- 2.DHCP作用
- 四、设计模式
- 1.工厂模式
- 总结
前言
一、C++相关 1.dynamic_cast的实现机制
dynamic的实现机制是根据class的vtbl虚函数表来实现的。
首先要知道一点,那就是dynamic_cast无法应用在缺乏虚函数的类型身上。
dynamic_cast通过寻找需要转型的对象虚函数表指针指向的虚函数表中的该对象类型的专属信息type_info,从而检验该对象的动态类型,通过这种方式来保证向下转型的安全性。
在编译的过程中,函数名将被转换成符号。
比如现在有两个重载函数:
void func(int i); void func(double j);
那么它们可能被C++编译器转换为 “函数名+参数变量” 的形式的符号
void func(int i); -> __funci void func(double j); -> __funcd
所以对于计算机而言,每个函数的符号都具有唯一性。
3.原始指针、unique_ptr和shared_ptr的使用场景答案见注释,答案来源:
https://blog.csdn.net/calmreason/article/details/88994106
class T3;
class T2;
class T1;
class A
{
T3* m_t2;//创建和释放都由A之外的代码管理,A只负责(借用)使用;业务逻辑上保证A在使用m_t2指向的对象的时候,对象始终是存在的
shared_ptr m_t2;//由加载程序创建m_t2指向的对象,执行时,交给A来管理,涉及动态对象的管理权的交接
unique_ptr m_t1;//A管理该对象的生命周期,A的构造函数构造m_t1, A的析构函数释放m_t1;
};
4.C和C++的适用性和场合?C++面向对象好在哪里?为什么嵌入式用C多?
C和C++的适用性和场合?
C语言:C语言是结构化和模块化的语言,是面向过程的。当程序的规模较小时,C语言运用起来得心应手。但是当问题比较复杂、程序的规模比较大的时候,C语言就会展现出它的局限性。
C++:正是因为有大规模的程序需要去处理,C++就应运而生了。C++是由C发展而来的,与C语言兼容。C++既可用于面向过程的结构化程序设计,也可用于面向对象的程序设计,是一种功能强大的混合型的程序设计语言。
C++面向对象好在哪里?
面向对象技术的出现就是为了解决软件的大规模可拓展性问题。
面向对象编程是一种编程经验的抽象集合,面向对象编程有三大优势:模块化、对象结构和组合/聚合思想,它们的核心理念都是在提升代码的可拓展性、可重用性和可维护性。
具体见链接:
https://blog.csdn.net/qq_37896578/article/details/123203886?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165900913716781790794082%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165900913716781790794082&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~pc_rank_v35-1-123203886-null-null.142v35experiment_28w_v1&utm_term=C%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%AF%AD%E8%A8%80%E7%9A%84%E4%BC%98%E5%8A%BF%E5%92%8C%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF&spm=1018.2226.3001.4187
为什么嵌入式用C多,而不是C++?
1 从移植性来说,C的移植性比较好,C语言在不同的软件平台拥有相同的语法。
2 从运行效率上来讲,C++编译器会做很多额外的工作,比如为了使程序通过编译暗自隐式类型转换、虚函数机制的虚函数指针的开销等等,因此比起C++,C语言的效率更高。
他们的区别在于make_shared只有一次内存申请操作,而shared_ptr构造函数会有两次(引用计数、堆区数据)。
make_shared可以分配单个内存块来保存这两个内存;从指向已分配对象的指针构造共享指针将需要分配第二个块来存储引用计数。除了这种效率之外,官方鼓励用make_shared函数来创建对象,而不要手动去new,这样就可以防止我们去使用原始指针创建多个引用计数体系。使用make_shared意味着您根本不需要处理new和原始指针,从而提供更好的异常安全性,在分配对象之后但在将其分配给智能指针之前不可能抛出异常。
6.POSIX C相关 7.static_cast 和 reinterpret_cast 的区别? 8.模板在哪个阶段进行处理? 9.private继承有什么用?在什么场景下使用?二、操作系统 1.共享内存怎么实现?
1 mmap() 实现共享内存;
2 shmat() 和 shmctl() 实现共享内存;
原理都是将普通文件映射到多个进程的地址空间,即做一个文件磁盘地址与进程虚拟内存地址空间的映射关系。这样进程就可以通过访问这个文件达到共享内存的目的。
生产者和消费者通过队列来通信,队列满时,不能生产;队列空时,不能消费。
condition_variable::wait(lock);
condition_variable::wait(lock, lambda);
如果只有一个参数,那么lock如果被占用,wait就会被阻塞。
如果两个参数,需要满足lock不被占用以及lambda返回true才能够获取锁。
#include3 有哪些锁?介绍它们的实现?#include #include #include #include #include using namespace std; mutex m_lock; condition_variable m_cv; deque m_data; int g_data; void Consumer(){ while(true){ unique_lock m_lck(m_lock); while(m_data.empty()){ m_cv.wait(m_lck); //阻塞该线程,直到其他线程notify_all } int data=m_data.front(); m_data.pop_front(); cout<<"get data: "< while(true){ unique_lock m_lck(m_lock); m_data.push_back(g_data); cout<<"add data: "< g_data=0; thread t1(Producer); thread t2(Consumer); t1.join(); t2.join(); return 0; }
互斥锁、自旋锁和读写锁。
1 互斥锁,就是一个整型,要么是0,要么是1,申请一块共享内存存放锁,使用关中断、硬件层面实现原子操作、锁内存总线等方式实现互斥锁。
2 自旋锁,可以通过 int test_and_set (int *lock); 这个原子操作来实现。
bool test_and_set(int *lock)
{
bool old=*lock;
*lock=true;
return old;
}
3 读写锁,当已经被加了读锁时,其他的读锁请求仍然可以访问,但是写模式锁不能访问(读写互斥);当写模式锁加锁时,其他的请求都不能访问。
#include4.单核CPU使用多线程是否能提高效率?#include using namespace std; mutex read_mtx; mutex write_mtx; int reader_cnt = 0; void Read(){ read_mtx.lock(); if(++reader_cnt == 1){ write_mtx.lock(); } read_mtx.unlock(); //read something read_mtx.lock(); if(--reader_cnt == 0){ write_mtx.unlock(); } read_mtx.unlock(); } void Write(){ write_mtx.lock(); //write something write_mtx.unlock(); }
首先要了解为什么要引入多线程?
假设有这样一个场景,程序只有一个单线程,当线程执行到某一步,需要等待IO资源或者其他资源时,程序将阻塞,CPU将空转,这样就浪费了CPU资源。
但是如果是多线程呢,就可以调度另外一个线程执行其他操作,这样就避免了CPU的空转,提高了CPU利用率,也减少程序整体的运行时间。
回到我们的问题,单核CPU使用多线程是否能提高效率呢?
对于CPU密集型的程序,多线程并不能提高运行效率。
对于IO密集型的程序,多线程可以提高运行效率。
原因上面已经解释了。
方法1:top -p PID,查看MEM进程内存占用率。
方法2:ps -aux | grep filename ,查看第五个数字。
条件变量适用于这样的情形:两个线程完成的任务之间有明确的先后顺序。比如三个线程顺序输出 abcabcabc…
7.系统调用是通过什么机制陷入内核的? 8.open与fopen的区别是什么?三、计算机网络 1. 为什么有了流量控制还要有拥塞控制?
因为二者的作用不一样。
流量控制主要是告诉数据的发送方,接收方这边缓存中还能接收多少数据,请发送方控制发送速率,从而减少丢包率。
拥塞控制是结合当前网络拥塞情况,来控制窗口大小,减少网络拥塞程度,从而提高数据传输的效率。
两者作用不同,但又相辅相成。
在网络中的主机,需要IP、子网掩码、网关等资源,而人工分配这些资源容易出错,所以DHCP协议的作用就是为网络中的主机自动分配这些资源。
四、设计模式 1.工厂模式
抽象工厂的基类是抽象基类,内部包含生产对象的纯虚函数。按照产品的不同派生多个派生类,每个类中生产自己的产品族。
总结


