• 忘掉天地
  • 仿佛也想不起自己
  • 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2021-02-16 05:08 Aet 隐藏边栏 |   抢沙发  8 
文章评分 2 次,平均分 5.0

模态对和非模态对话框

模态对话框

当它弹出后,本应用其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作并退出后,其他窗口才能与用户交互。

非模态对话框

它弹出后,本程序其他窗口仍能响应用户输入。

消息循环机制

Windows是事件驱动的。
Windows有两个关键的入口。一个是WinMain,一个是WindowProc
其中WinMain函数是应用程序的入口。
至于WindowProc,在Windows里面,应用程序是不直接调用任何窗口函数的,而是等待Windows去调用窗口函数,请求完成任务或返回信息。而为了保证Windows调用某个窗口函数,该函数必须先向Windows登记,然后在Windows实施相应操作后回调,所以窗口函数又称为回调函数。WindowProc是一个主回调函数。

WIN32编程过程

注册窗口类

窗口种类是定义窗口的模板,这些属性包括窗口样式,鼠标形状,菜单等等。

建立窗口就是用WNDCLASS结构定义一个结构变量。

创建窗口

显示和更新窗口

CreateWindow创建完窗口后,要想把它显示出现,还必须调用另一个API函数ShowWindows

创建消息循环

Windows为每个正在运行的应用程序都保持一个消息队列。当你按下鼠标或者键盘时,Windows并不是把这个输入事件直接送给应用程序,而是将输入的事件先翻译成一个消息,然后把这个消息放入到这个应用程序的消息队列中去。

GetMessage收到一个WM_QUIT消息,则返回FALSE,如收到其他消息,则返回TRUE。因此,在接收到WM_QUIT之前,带有GetMessage()的消息循环可以一直循环下去。只有当收到的消息是WM_QUIT时,GetMessage才返回FALSE,结束消息循环,从而终止应用程序。

消息用GetMessage读入后,它首先要经过函数TranslateMessage()进行翻译,这个函数会转换成一些键盘消息,它检索匹配的WM_KEYDOWNWM_KEYUP消息,并为窗口产生相应的ASCII字符消息(WM_CHAR)。

下一个函数调用DispatchMessage()要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程。Windows会调用函数WindowsProc()来处理这个消息。在WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了一个消息循环。

终止应用程序

Windows是一种非剥夺式多任务操作系统。只有的应用程序交出CPU控制权后,Windows才能把控制权交给其他应用程序。当GetMessage函数找不到等待应用程序处理的消息时,自动交出控制权,WindowsCPU的控制权交给其他等待控制权的应用程序。

窗口过程

GetMessage负责从应用程序的消息队列中取出消息,而函数DispatchMessage()要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程。

GetMessage&&PeekMessage

PeekMessage在处理获得消息时候和GetMessage一样,关键不同的是PeekMessage在没有消息处理的时候还会继续保持循环激活状态,并且继续占用资源。

  • GetMessage每次都会等待消息,直到取到消息才会返回。PeekMessage只是查询消息队列,没有消息就立即返回,从返回值判断是否取到了消息。
  • GetMessage从消息队列中取不到消息,则线程就会被操作系统挂起,等待OS重新调度该线程;而PeekMessage线程会得到CPU的控制权,运行一段时间。
  • GetMessage是从消息队列中“取出”消息,就把消息从消息队列中删除;PeekMessage的主要功能是“窥视”消息,如果有消息,就返回true,否则返回false。另外,也可以使用PeekMessage从消息队列中取出消息,这个功能涉及到它的一个参数(UINT wRemoveMsg),如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出。

进程间通讯方式

  • 管道
  • 消息队列
  • 信号量
  • 共享内存
  • socket

线程间通讯方式

  • 全局变量
  • 互斥量
  • 信号量
  • 事件
  • 临界区

vector和list

  • vector是一段连续的内存空间,是物理上的连续;而list底层是双向链表实现的,它的节点之间是通过指针来体现出逻辑上的连续,在内存分配上,不是连续的空间。
  • vector由于是连续的内存,所以它支持随机访问,时间复杂度为O(1);而list则需要通过指针来遍历,时间复杂度是O(n)
  • vector是连续的空间,所以它插入删除元素,就可能需要元素移动拷贝等操作;list插入删除不涉及数据的激动,改变相关节点的后继或前驱指针的值即可。
  • 添加元素时,vector由于涉及空间的重新分配,所以指向容器的迭代器、指针以及引用会全部失效;而list则全都不失效。
  • 删除元素时,vector是被删除元素之前的迭代器是有效;list删除元素的时候也是全都不失效。

虚函数表创建的时机

虚函数表是在编译时确定下来的。

  • 没有继承(类有虚函数)
    • 一个虚函数表;数据在低地址,vptr在高地址;虚函数表里面,虚析构相对其他虚函数地址更低,先申明的虚函数在低地址,后申明的虚函数在高地址。
  • 单一继承()

编译时多态和运行时多态

对模板参数而言,多态是通过模板具现化和函数重载解析实现的。以不同的模板参数具现化导致调用不同的函数,这就是所谓的编译期多态

运行期多态的设计思想要归结到类继承体系的设计上去。对于有相关功能的对象集合,我们总希望能够抽象出它们共有的功能集合,在基类中将这些功能声明为虚接口(虚函数),然后由子类继承基类去重写这些虚接口,以实现子类特有的具体功能。

编译期优缺点

  • 带来了泛型编程的概念。具有很强的适配性和松耦合性,对于特殊类型可以由模板偏特化、全特化处理。
  • 程序可读性低。无法实现模板的分离编译。无法处理异质对象集合。

运行期优缺点

  • 能处理同一个继承体系下的异质类集合。
  • 运行期间进行虚函数绑定,提高了程序运行开销;类继承体系庞大时,对接口的修改容易影响到类的层次;由于虚函数在运行期确定,所有编译器无法对虚函数进行优化;虚函数表指针增大了对象体积,类也多了一张虚函数表。

TCP和UDP的区别

TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接。
在数据传递时,有确认、窗口、重传、拥塞控制机制。
在数据传完后,还会断开连接用来节约系统资源。

慢,效率低,占用系统资源高,易被攻击。

UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。

不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

TCP UDP
面向连接 面向无连接
TCP对系统资源要求多 UDP对系统资源要求少
TCP程序结构复杂 UDP程序结构简单
数据流模式 数据报模式
保证数据的完整性 可能发生丢包
保证数据的顺序 不保证
速度慢 速度快
适合少量数据场景 适合大量数据场景

客户端探测是否成功连接服务端用TCP还是UDP

map和set

底层数据结构是红黑树。

map是以键值的方式存储的。键是pair类型的first,值是pair类型的second.
set存储的只有一个key。

智能指针

多态

在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。

构造函数是否可为虚

  • 虚函数对应一个虚函数表,如果构造是虚的,就需要通过虚函数表来调用,但是对象都还没实例化,根本没有内存空间,也就找不到虚函数表
  • 构造函数不允许是虚函数,因为创建一个对象时我们总要明确指定对象的类型,而如果是虚的,具体的类型要在运行时才能确定
  • vptr是在是在构造调用后才确定,所以构造不能为虚

结构体对齐

有些平台每次读都是从偶地址开始,如果是一个int(32位系统)存放在偶地址开始的地方,那么读一个周期就可以读出;如果存放在奇地址开始的地方,可能会需要2个读周期,并对2次读出的结果的高低字节进行拼凑才能得到该int型数据。

对于对齐的实现,通常我们写程序时是不需要考虑对齐问题的。因为编译器会替我们选择合适目标平台的对齐策略。

准则

字节对齐的细节和编译器的实现是相关的,一般而言,需要满足3个准则:

  • 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
  • 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要,编译器会在成员之间加上填充字节;
  • 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节。

联合体

联合体的大小取决于它所有成员中占有空间最大的一个成员的大小。

额外

编译器会尽力把数据放在它的对齐上以提高内存的命中率。
对齐是可以更改的
使用#pragma pack(x)可以改变编译器的对齐方式。C++固有类型的对齐取编译器对齐方式与自身大小中较小的一个。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2022-09-22
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享