mirror of
https://github.com/CaiJimmy/hugo-theme-stack.git
synced 2025-04-29 03:53:30 +08:00
c++
This commit is contained in:
parent
f434569f7d
commit
45762d8956
@ -17,19 +17,113 @@ This article offers a sample of basic Markdown.
|
|||||||
|
|
||||||
# 正文开始
|
# 正文开始
|
||||||
|
|
||||||
1.struct和class的区别
|
在线编程工具:
|
||||||
|
|
||||||
2.值传递,地址传递,引用传递(拷贝)的区别
|
https://www.bejson.com/runcode/c740/
|
||||||
|
|
||||||
4.指针是几个字节?
|
|
||||||
|
|
||||||
5.static关键字
|
|
||||||
|
|
||||||
6.虚函数指针,虚函数表
|
sizeof(空类) = 1;
|
||||||
|
|
||||||
7.多态
|
静态成员变量和成员函数都不占类的大小(sizeof),也就是说静态成员变量和成员函数都不属于类
|
||||||
|
|
||||||
8.编译器如何知道你是进行的函数重载
|
|
||||||
|
|
||||||
|
```
|
||||||
|
继承下面说了
|
||||||
|
|
||||||
|
封装:将变量设置为protected或者provate,限制这些变量在类外的直接访问,我们可以使用get常量函数来完成对这个变量的封装
|
||||||
|
|
||||||
|
protected:当一个成员被定义为protected类型时,仅能在类内、友元和派类访问。
|
||||||
|
|
||||||
|
private:当一个成员被定义为private类型时,仅能在类内、友元访问。
|
||||||
|
|
||||||
|
多态下面说了
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 1.struct和class的区别
|
||||||
|
|
||||||
|
首先,class是cpp独有的,c语言里面没有,
|
||||||
|
|
||||||
|
然后就是在cpp中,class的默认访问权限是private,而struct是public;
|
||||||
|
|
||||||
|
还有就是class默认都是私有继承,而sruct默认是公有继承.
|
||||||
|
|
||||||
|
最后一点是,在语法上的区别,你使用cpp中 ,
|
||||||
|
|
||||||
|
不管是struct还是class,都可以直接使用类名.
|
||||||
|
|
||||||
|
在c语言中,要么写 struct A a;(带上struct),要么你用typedef struct A A;一下
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/136666085?spm=1001.2014.3001.5501
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
补充:公有继承,保护继承与私有继承下,类内的元素的权限变化:
|
||||||
|
|
||||||
|
- 公有继承:原来啥权限就还是啥权限,一点不变
|
||||||
|
- 保护继承:原来公有变保护,其他两个->原来啥权限就还是啥权限
|
||||||
|
- 私有继承:原来公有变私有,原来保护变私有,原来私有还是私有
|
||||||
|
|
||||||
|
## 2.值传递,地址传递,引用传递(拷贝)的区别
|
||||||
|
|
||||||
|
值传递你无法在函数中改变这个变量的值
|
||||||
|
|
||||||
|
地址传递和引用你可以在函数中改变这个变量的值
|
||||||
|
|
||||||
|
值传递相当于是你建立了一个副本,你是你,他是他,你的改变无法影响到他,他的改变无法影响到你.
|
||||||
|
|
||||||
|
地址传递的话,传进去的就是本人了,此时修改地址上的数据会影响到原始数据.
|
||||||
|
|
||||||
|
而引用传递相当于是给该变量取的别名,相当于是一个大名一个小名比如鲁迅和周树人,本质上还是一个人,所以改变引用传递的变量也可以改变变量的原始数据
|
||||||
|
|
||||||
|
## 4.指针是几个字节?
|
||||||
|
|
||||||
|
64位系统是8字节
|
||||||
|
|
||||||
|
32位系统是4字节
|
||||||
|
|
||||||
|
## 5.static关键字
|
||||||
|
|
||||||
|
static的用法分为静态变量与静态函数
|
||||||
|
|
||||||
|
静态变量将变量限定在当前文件下,且生命周期和该文件运行的周期一样长.
|
||||||
|
|
||||||
|
然后再细分就是局部静态变量与全局静态变量:局部静态变量被限定在一个代码块内(一般是一个函数),而全局静态变量只要是在这个文件内,都可以访问.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
再者就是静态函数了,<font color=red>静态成员函数只能访问静态成员变量</font>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
然后就是,类中的静态成员变量并不属于这个类,你用sizeof去算,他不算这个类的大小
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
涉及知识:cpp编译单元 https://blog.csdn.net/weixin_52668597/article/details/137575061?spm=1001.2014.3001.5501
|
||||||
|
|
||||||
|
## 6.虚函数指针,虚函数表
|
||||||
|
|
||||||
|
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/137447982?spm=1001.2014.3001.5501
|
||||||
|
|
||||||
|
只要你在类中写了一个虚函数,那么就会产生一个虚函数表.
|
||||||
|
|
||||||
|
而且不管你写多少个虚函数,这些虚函数在类中所占的内存就只有8个字节,而占的这八个字节就是虚函数指针,也就是说,这些虚函数都放在一个数组中,这个数组就是虚函数表
|
||||||
|
|
||||||
|
## 7.多态
|
||||||
|
|
||||||
|
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/137447982?spm=1001.2014.3001.5501
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
多态其实就是 父类指针指向子类对象,如果子类重写了父类的方法,那么这个父类指针就会呈现出不同的现象
|
||||||
|
|
||||||
|
## 8.编译器如何知道你是进行的函数重载
|
||||||
|
|
||||||
答:函数重载,它允许在同一个作用域中定义多个同名函数,但这些函数的<font color=red>参数列表或类型</font>必须不同。在调用这些函数时,编译器会根据传递给<font color=red>函数的参数的数量、类型或顺序</font>来确定要调用的具体函数版本。
|
答:函数重载,它允许在同一个作用域中定义多个同名函数,但这些函数的<font color=red>参数列表或类型</font>必须不同。在调用这些函数时,编译器会根据传递给<font color=red>函数的参数的数量、类型或顺序</font>来确定要调用的具体函数版本。
|
||||||
|
|
||||||
@ -41,7 +135,7 @@ This article offers a sample of basic Markdown.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
9.构造,析构的顺序
|
## 9.构造,析构的顺序
|
||||||
|
|
||||||
在C++中,对象的构造和析构顺序
|
在C++中,对象的构造和析构顺序
|
||||||
|
|
||||||
@ -80,9 +174,48 @@ Child::fun()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
10.stl:vector、list、Map的区别
|
## 10.stl:vector、list、Map的区别
|
||||||
|
|
||||||
11.智能指针
|
vector:底层是一个动态数组,可以通过下标进行快速随机访问,占据连续的内存,在不扩容的情况下,在尾部增删很快.在扩容的情况下,需要先开辟原来容器大小的1.5倍,再将原数据拷贝到新的内存,最后在释放原内存
|
||||||
|
|
||||||
|
list:是一个双向链表,他虽然也可以用下标访问,但是那是因为他重载了中括号运算符,他访问一个元素的复杂度是o(n),他的内存是不连续的,节点之间通过指针连接.他唯一的优势是可以快速的在任意位置进行增删,但前提是先经过o(n)的复杂度找到这个位置
|
||||||
|
|
||||||
|
Map:是一个键值对,类似于json那种结构,底层是红黑树实现.
|
||||||
|
|
||||||
|
每个键都是唯一的(键和值可以为null,但是键只能出现一次),
|
||||||
|
|
||||||
|
map在插入好删除时会自动排序,他对元素的访问、插入和删除操作,这些操作的时间复杂度通常是对数时间(即`O(log n)`)。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include<iostream>
|
||||||
|
#include<map>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class A{};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
map<A*,int> m1,m2;
|
||||||
|
m1[nullptr] = 1;
|
||||||
|
A *a = new A();
|
||||||
|
m2[a] = 2;
|
||||||
|
|
||||||
|
printf("%d,%d",m1[nullptr],m2[a]);
|
||||||
|
|
||||||
|
map<A*,A*> m3;
|
||||||
|
m3[nullptr] = nullptr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 11.智能指针
|
||||||
|
|
||||||
智能指针有auto_ptr,share_ptr,unique_ptr还有shared_ptr
|
智能指针有auto_ptr,share_ptr,unique_ptr还有shared_ptr
|
||||||
|
|
||||||
@ -109,11 +242,17 @@ auto_ptr是C++98中引入的第一个智能指针,但是由于他的不安全
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
12.项目中如何保证线程安全?
|
## 12.项目中如何保证线程安全?(如何避免死锁)
|
||||||
|
|
||||||
13.死锁
|
加锁:**互斥锁**,**读写锁**,cpp中特有的智能锁
|
||||||
|
|
||||||
14.多线程中多个信号与主线程
|
## 13.死锁
|
||||||
|
|
||||||
|
死锁产生的条件:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 14.多线程中多个信号与主线程
|
||||||
|
|
||||||
主线程一般是负责控制和协调其他线程的任务。比如说我这个共享单车项目中的服务器,他的主线程主要是负责监听客户端的连接,一旦有客户端来进行连接,我们就会把这个客户端通过libevent变成一个事件,并把他加入到事件集合中去,然后由其他线程来监听该客户端的读写事件,并通过轮询的方式拿到线程池中的一个线程,然后由这个线程通过调用它自己的回调函数来处理这个读写事件.相当于主线程就是是负责统筹规划的,他只复制监听客户端,剩下的交给其他线程.
|
主线程一般是负责控制和协调其他线程的任务。比如说我这个共享单车项目中的服务器,他的主线程主要是负责监听客户端的连接,一旦有客户端来进行连接,我们就会把这个客户端通过libevent变成一个事件,并把他加入到事件集合中去,然后由其他线程来监听该客户端的读写事件,并通过轮询的方式拿到线程池中的一个线程,然后由这个线程通过调用它自己的回调函数来处理这个读写事件.相当于主线程就是是负责统筹规划的,他只复制监听客户端,剩下的交给其他线程.
|
||||||
|
|
||||||
@ -127,35 +266,119 @@ auto_ptr是C++98中引入的第一个智能指针,但是由于他的不安全
|
|||||||
|
|
||||||
常见模式有:
|
常见模式有:
|
||||||
|
|
||||||
1. **条件变量(Condition Variables)**:相当于是一种基于互斥锁的线程间同步机制,通常情况下是和锁一起使用的。主线程可以使用条件变量来等待特定的条件达成,而其他线程则可以通过发送信号来通知主线程条件的改变。一旦条件满足,主线程就会被唤醒并继续执行。
|
1). **条件变量(Condition Variables)**:相当于是一种基于互斥锁的线程间同步机制,通常情况下是和锁一起使用的。主线程可以使用条件变量来等待特定的条件达成,而其他线程则可以通过发送信号来通知主线程条件的改变。一旦条件满足,主线程就会被唤醒并继续执行。
|
||||||
|
|
||||||
2. **事件(Events)**:事件也是一种用于线程间同步的通信机制,通常用于向其他线程发出信号以触发特定事件的发生,然后执行事件的回调函数。主线程可以等待某个事件的发生,其他线程可以通过发送信号来触发该事件。
|
2). **事件(Events)**:事件也是一种用于线程间同步的通信机制,通常用于向其他线程发出信号以触发特定事件的发生,然后执行事件的回调函数。主线程可以等待某个事件的发生,其他线程可以通过发送信号来触发该事件。
|
||||||
|
|
||||||
3. **信号量(Semaphores)**:
|
3). **信号量(Semaphores)**:
|
||||||
|
|
||||||
信号量维护一个计数器,表示可用资源的数量。线程可以通过请求(等待)和释放(发信号)操作来获取和释放资源。当计数器为正时,线程可以继续执行,否则线程会被阻塞直到资源可用。就是我们常说的那个操作系统pv操作,经常用来解决“生产者消费者的问腿”
|
信号量维护一个计数器,表示可用资源的数量。线程可以通过请求(等待)和释放(发信号)操作来获取和释放资源。当计数器为正时,线程可以继续执行,否则线程会被阻塞直到资源可用。就是我们常说的那个操作系统pv操作,经常用来解决“生产者消费者的问题”,当然信号量也是可以的
|
||||||
|
|
||||||
伪代码:
|
伪代码:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
待补充。。。
|
生产者和消费者都可以有很多个
|
||||||
```
|
|
||||||
|
情况有三种:
|
||||||
|
1.队列已满,生产者停止生产商品 -> 生产者wait条件变量
|
||||||
|
2.队列为空,消费者无商品可取 -> 消费者wait条件变量
|
||||||
4. **消息队列(Message Queues)**:主线程可以通过发送消息到队列中来通知其他线程,而其他线程则可以从队列中接收消息并执行相应的操作。
|
3.队列不满但非空,生产者正常生产商品,消费者正常取商品
|
||||||
|
|
||||||
|
#include "需要的头文件"
|
||||||
|
|
||||||
|
//wait()-> P()操作 --
|
||||||
|
//signal()-> V()操作 ++
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int value; //剩余资源数
|
||||||
|
struct process *list;//等待队列
|
||||||
|
} semaphore;
|
||||||
|
|
||||||
|
semaphore empty,full;//空位和产品的数量 空位数+产品数=最大容量
|
||||||
|
Mutex mutex1,mutex2;//两个互斥锁
|
||||||
|
|
||||||
|
//申请使用资源
|
||||||
|
void wait(semaphore s)
|
||||||
|
{
|
||||||
|
s.value --;
|
||||||
|
if(s.value < 0)//剪完1后,可能等于0(表示资源刚好用完,但是够用,所以不阻塞),也可能<0(资源早就用完了,再减一就没得用了,所以要阻塞)
|
||||||
|
{
|
||||||
|
block(s.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用完释放资源
|
||||||
|
void signal(semaphore s)
|
||||||
|
{
|
||||||
|
s.value ++;
|
||||||
|
if(s.value <= 0)//刚释放完一个资源(也就是说现在有一个资源可用),发现资源数==0,说明说明之前是<0的,表示队列已经阻塞了;如果发现资源数<0,那就更不用说了,肯定有消费者在等待
|
||||||
|
{
|
||||||
|
wakeup(s.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 生产者函数
|
||||||
|
void producer() {
|
||||||
|
while (1) {
|
||||||
|
produce();//生产1个东西
|
||||||
|
wait(empty);//空位减1个
|
||||||
|
wait(mutex1);//上锁
|
||||||
|
|
||||||
|
array[空位] = 产品;//给一个空位放产品
|
||||||
|
|
||||||
|
signal(mutex1);//解锁
|
||||||
|
signal(full);//产品数+1
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 消费者函数
|
||||||
|
void consumer() {
|
||||||
|
while (1) {
|
||||||
|
wait(full);//产品数-1
|
||||||
|
wait(mutex2);//上锁
|
||||||
|
|
||||||
|
array[产品数] = null;//拿走一个产品
|
||||||
|
|
||||||
|
signal(mutex2);//解锁
|
||||||
|
signal(empty);//空位+1
|
||||||
|
|
||||||
|
comsum();//消费这个产品
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::thread prod(producer);
|
||||||
|
std::thread cons(consumer);
|
||||||
|
prod.join();
|
||||||
|
cons.join();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
信号量(Semaphore):
|
||||||
|
信号量是一种用于控制对共享资源的访问的同步机制。它通常用于实现进程或线程间的协调。信号量主要包含两种操作:wait()(或称为P()操作)和 signal()(或称为V()操作)。wait()操作会减少信号量的计数,如果结果为负数,则线程会阻塞。signal()操作会增加信号量的计数,如果有线程正在阻塞,它会被唤醒。
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
4). **消息队列(Message Queues)**:主线程可以通过发送消息到队列中来通知其他线程,而其他线程则可以从队列中接收消息并执行相应的操作。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
15.qt信号槽中有第五个参数,有了解过吗?
|
||||||
|
|
||||||
|
信号槽中有第五个参数支持qt中,信号与槽进行跨跨线程通信,他是一个枚举值,
|
||||||
|
默认是自动连接,也比较智能,如果信号与槽是在同一个线程,就直接调用槽函数,如果不在同一个线程,会自动使用QueuedConnection.
|
||||||
|
|
||||||
|
然后支持多线程的枚举值其实有两个,一个是Queued Connection,另一个是BlockingQueuedConnection,这两个支持信号与槽的异步通信,唯一的区别是:
|
||||||
|
|
||||||
|
Queued Connection是异步非阻塞的,BlockingQueuedConnection是异步阻塞的,然后非阻塞是运行后直接返回,阻塞是运行结束后才返回.
|
||||||
|
Queued Connection用的比较多,他可以保证槽函数的调用是在接收者的线程中进行的,所以就不会有多个线程同时访问槽函数中的共享资源的情况发生(除非槽函数内部又进行了不安全的跨线程操作),这样就避免线程竞争,避免了线程安全的问题。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BIN
exampleSite/content/post/2024-04-19面试复盘/图片/1713633820870.png
Normal file
BIN
exampleSite/content/post/2024-04-19面试复盘/图片/1713633820870.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
Loading…
Reference in New Issue
Block a user