当前位置: 首页 > news >正文

C++ / MFC / Qt / C# 核心知识点汇总笔记

C++ / MFC / Qt / C# 核心知识点汇总笔记

目录

  1. 浅拷贝 & 深拷贝 & 内存分布
  2. new 底层做了什么
  3. 类有指针成员为什么必须重载赋值运算符
  4. Qt 信号槽 & &符号含义 & 函数指针原理
  5. MFC _T() / TCHAR / w宽字符 详解
  6. MFC 为什么大量用 #define 宏
  7. MFC 为什么不用虚函数、偏用宏做消息映射
  8. WinForm 与 MFC 设计差异
  9. 模态对话框 含义 & 由来
  10. 常量指针 & 指针常量 区分

1. 浅拷贝 & 深拷贝 & 内存分布

浅拷贝

编译器默认拷贝构造/默认赋值,只按字节逐成员赋值
类中有裸指针时:只拷贝指针地址,不新开堆内存。

  • 两个对象指针指向同一块堆内存
  • 修改一个对象的指针内容,另一个跟着变
  • 析构时重复释放同一块内存 → 程序崩溃

深拷贝

手动自定义拷贝构造、重载赋值运算符:

  • 不直接赋值指针地址
  • 重新new/malloc开辟独立堆内存
  • 再把内容拷贝过去

内存分布对比

浅拷贝内存

栈区:p1、p2 对象各自独立 p1.pName 、p2.pName 存同一个堆地址 堆区:只有一份字符串内容,两人共用

深拷贝内存

栈区:p1、p2 对象独立 堆区:p1 一份内存、p2 单独新开一份内存 各自指向独立堆空间,互不干扰

修改 p1.pName 影响

  • 浅拷贝:改 p1 会连带改 p2
  • 深拷贝:改 p1完全不影响 p2

2. new 底层做了什么

Person* p = new Person("xxx",20);底层三件事:

  1. 堆内存申请一块足够存放对象的空间
  2. 调用类构造函数初始化成员
  3. 把堆起始地址返回给栈上的指针p

对象内存位置

  • 指针变量p:在
  • Person 对象本体:在
  • 对象内指针成员再指向另一块堆字符串

delete 底层做什么

  1. 先调用析构函数(释放内部指针堆内存)
  2. 释放 new 申请的对象本身堆内存

关键

new 出来的堆对象不会自动析构,必须手动 delete。


3. 类有指针成员 必须重载=运算符?

结论

类包含裸指针、构造里手动new/malloc、析构要delete/free
👉必须自定义:拷贝构造 + 赋值运算符重载 + 析构(C++三法则)

不重载=的后果

  1. 默认赋值是浅拷贝,指针同指向一块堆内存
  2. 旧内存丢失 →内存泄漏
  3. 析构重复释放 →程序崩溃

什么时候不用重载

成员都是int/double/std::string等,无裸指针、无手动堆内存申请。
std::string替代char*可彻底避开浅拷贝问题。


4. Qt 信号槽 & &符号 & 函数指针底层

Qt信号槽 对应 C#

  • Qtsignals👉 C#event
  • Qtslots👉 C# 普通订阅方法
  • Qtconnect()👉 C#+=绑定
  • Qtemit👉 C#Invoke()触发

& 在 &类::函数名 含义

  • 普通函数名本身就是地址,可隐式转函数指针
  • 类成员函数不能隐式转地址,C++语法强制加&
    👉&Sender::mySignal=显式取成员函数入口地址,当做函数指针传参

为什么成员函数必须加&

  1. 成员函数隐含this指针,不是独立裸函数
  2. 类有函数重载,A::f有语法歧义,分不清重载版本
  3. 成员函数指针不是单纯地址,是复合结构
  4. C++标准禁止成员函数名隐式转地址

信号槽底层原理

本质:哈希映射表 + 成员函数指针遍历调用

  1. connect:把 信号地址、接收对象、槽函数指针 存入映射表
  2. emit:查表 → 遍历所有绑定的槽 → 逐个通过函数指针调用

跨线程信号槽:不是直接调用,而是封装成消息入队列,在目标线程执行。

函数指针怎么知道函数起止内存

  • 函数指针只存起始地址
  • 不需要存结束地址,CPU 执行到汇编ret指令自动结束函数
  • 若要人为获取起止,需解析PE文件/编译器扩展。

5. MFC _T() / TCHAR / 宽字符

_T() 作用

适配ANSI(多字节)/Unicode(宽字符)双字符集,一套代码通用。

底层宏定义

#ifdef_UNICODE#define_T(x)L##x#else#define_T(x)x#endif
  • Unicode:_T("abc")L"abc"
  • 多字节:_T("abc")"abc"

w 前缀含义

w = wide 宽字符

  • char:1字节窄字符
  • wchar_t:2字节宽字符,可存中文
  • L"字符串":宽字符串字面量
  • wcslen/wcscpy:宽字符字符串函数

配套通用类型

  • TCHAR:自动适配 char / wchar_t
  • LPCTSTR/LPTSTR:自适应字符串指针
  • _tcsxxx:自适应字符串函数

三种字符串区别

  • "xxx":固定 char 窄字符串
  • L"xxx":固定 wchar_t 宽字符串
  • _T("xxx"):编译时自动适配

6. MFC 为什么大量用 #define 宏

  1. 适配ANSI/Unicode双字符集(最主要)
  2. 简化极复杂C++语法(消息映射宏)
  3. 兼容不同编译器、VC版本、32/64位架构
  4. 功能开关裁剪,控制编译模块
  5. 生成重复模板代码,减少手写量

7. MFC 为什么不用虚函数,偏用宏做消息映射

  1. 年代硬件差:全做虚函数,虚表内存开销爆炸,99%消息用不到却要全承载
  2. Windows 消息无限新增,虚函数基类要频繁改动、全部重编译
  3. 虚函数编译期绑定,不支持运行时消息路由、动态拦截
  4. 要兼容原生C语言窗口回调机制,虚函数适配困难
  5. 宏可自动生成映射表模板代码,统一规范

8. WinForm 对比 MFC

  1. WinForm 高层封装,彻底屏蔽原生Win32消息,无宏、无消息映射
  2. C# 原生事件+委托直接替代 MFC 消息映射
  3. 硬件性能充足,不在乎虚表内存开销,直接用虚函数重写
  4. WinForm 底层封装Win32,上层只暴露Click/Load/Paint等高阶事件
  5. WinForm:Show()非模态 /ShowDialog()模态

9. 模态对话框 含义 & 由来

通俗理解

模态:强制锁定在当前弹窗模式,必须处理完关闭后,才能操作父窗口
非模态:弹窗打开,仍可自由操作主窗口。

底层原理

  • 模态:禁用父窗口,内部独立消息循环,阻塞等待关闭
  • 非模态:不禁用父窗口,共用消息循环

调用方式

  • MFC:模态DoModal();非模态Create()+ShowWindow()
  • WinForm:模态ShowDialog();非模态Show()

模态词源

源自拉丁语modus模式/状态;
逻辑学、语法情态动词引申为强制、必须遵从当前模式
GUI借用该概念:强制用户停留在弹窗交互模式。


10. 常量指针 & 指针常量

记忆规则

const离谁近,谁不可修改;
const*左:常量指针;const*右:指针常量。

常量指针

constint*p;
  • 指向的值不可改*p = 100报错
  • 指针本身指向可以改p = &b
    口诀:指向常量,指针能变

指针常量

int*constp;
  • 指针本身指向不可改
  • 指向的值可以改*p = 100
    口诀:指针本身是常量,指向不能变

双重锁定

constint*constp;

值不能改、地址也不能改。


C++ 指针、数组、数组指针、指针数组、[]与.-> 全套精讲

一、基础代码示例

classPerson{public:string name;intage;Person(string n,inta):name(n),age(a){}voidshowPerson(){cout<<name<<" "<<age<<endl;}};// 动态开辟对象数组Person*arr2=newPerson[2]{Person("lucy",18),Person("bob",20)};// 四种等价调用(*(arr2+0)).showPerson();arr2[0].showPerson();(arr2+1)->showPerson();(*(arr2+1)).showPerson();delete[]arr2;

二、为什么Person* arr2可以用arr2[0]

1. 核心等价公式(C++ 铁律)

p[i]<==>*(p+i)

只要是指针,指向连续同类型内存,都可以用[下标]写法

2. 逐层推导

  • arr2类型:Person*(指向数组首元素的指针)
  • arr2 + 0:还是Person*指针
  • *(arr2 + 0)解引用,拿到实体对象 Person
  • arr2[0]等价于*(arr2+0)→ 本身就是对象

3. 关键区分

  • arr2 + i→ 指针Person*
  • arr2[i]→ 实体对象Person

三、为什么arr2[0]是对象,不是指针

  1. arr2Person*,存的是首元素地址
  2. arr2[0]自带隐式解引用*
  3. 解引用后,访问到内存里真实的 Person 实例
  4. 类型从Person*变成Person

通俗比喻:
arr2 是手指(指针)
arr2+0 还是手指
arr2[0] 顺着手指找到真人(实体对象)


四、.->运算符终极规则

1. 使用铁律

  • 实体对象 / 引用→ 用.
  • 对象指针→ 用->

2. 等价对照

// 指针 -> 用 ->(arr2+0)->showPerson();// 解引用得到对象 -> 用 .(*arr2).showPerson();arr2[0].showPerson();(*(arr2+0)).showPerson();

3. 错误写法

(*arr2)->showPerson();// 错误:*arr2 是对象,不能用 ->arr2[0]->showPerson();// 错误:arr2[0] 是对象,不能用 ->

五、指针数组 vs 数组指针(彻底分清)

前置优先级

[]优先级高于*

1. 指针数组

写法:Person* arr[2]

  • 无括号,arr[2]先结合 → 是数组
  • 每个元素类型Person*→ 数组里存指针
  • 本质:数组装指针

内存:多个指针,可指向零散不连续对象。

2. 数组指针

写法:Person (*p)[2]

  • 括号把*p包起来 → 先结合成指针
  • 后面[2]→ 指向一整个含2个Person的数组
  • 本质:指针指向整个数组

内存:一整块连续数组,p++直接跳过整个数组大小

3. 普通指针(你代码里的)

写法:Person* arr2

  • 既不是指针数组,也不是数组指针
  • 只是指向数组首元素的普通对象指针
  • arr2++只跳过一个 Person 对象大小

4. 三者一眼区分

写法名称本质
Person* arr2普通元素指针指向单个/数组首元素
Person* arr[2]指针数组数组,元素是指针
Person (*p)[2]数组指针指针,指向整个数组

5. 记忆口诀

  • 括号包星:数组指针
  • 无括号先数组:指针数组

六、关键类型汇总

表达式类型用法
arr2Person*指针
arr2+0Person*指针,用->
*arr2Person对象,用.
arr2[0]Person对象,用.

七、一句话终极总结

  1. 指针可以用[]arr2[i] = *(arr2+i)
  2. 带下标[]就是隐式解引用,得到实体对象,用.
  3. 不带下标、变量+i是指针,用->
  4. 无括号是指针数组,带括号包星是数组指针
  5. Person* arr2只是普通首元素指针,不属于上面两者
http://www.jsqmd.com/news/794901/

相关文章:

  • 2026年五大听书软件横评,QQ阅读、书尖AI 一篇说清楚 - 资讯焦点
  • 鸣潮终极解放指南:如何用ok-ww后台自动化工具每天节省2小时游戏时间
  • 如何突破《原神》60帧限制:终极帧率解锁完全指南
  • 2026上海GEO优化公司:制造业、服务业、化工行业GEO优化公司推荐 - 资讯焦点
  • 手把手教你搭建专属 AI 助手|hermes agent 2 分钟极速部署指南! - 博客万
  • 从蛋白质分类到社交网络:Graph Pooling在实际项目里到底怎么用?
  • 终极指南:3分钟解锁网易云音乐NCM加密文件,纯C语言工具一键转换
  • RasaGPT:融合Rasa与GPT构建智能对话机器人的工程实践
  • 八大网盘直链下载终极指南:免费获取真实下载地址的完整解决方案
  • BetterNCM安装器:3分钟让网易云音乐焕然一新
  • 从踩坑到逆袭:我如何找到靠谱有实力的企业IP打造服务商
  • Stacking集成学习避坑指南:为什么你的模型融合后效果反而变差了?
  • 5.4-5.10 补题
  • LLM上下文窗口工程2026:超长文档处理的实战策略完全指南
  • Reloaded-II 游戏模组管理框架:告别繁琐安装,开启智能模组新时代
  • MCA Selector终极指南:掌握Minecraft区块管理核心技术
  • idea postgreSQL不显示所有的表
  • 企业级AI低代码平台kweaver-dip:架构解析与工作流实战
  • 2026年热门美容面罩美容仪真实测评推荐,挑选避坑指南 - 博客万
  • Hotkey Detective:Windows热键冲突终极解决方案与实战指南
  • 如何将旧电视盒子变成强大Linux服务器:5步终极改造指南
  • FunClip:基于ASR与NLP的AI视频精准剪切工具实战指南
  • 三步轻松批量下载微博相册高清图片:告别手动保存的烦恼
  • Android虚拟定位终极指南:无需Root的应用级位置伪装解决方案
  • 久坐骨骼亚健康适合哪种液体钙?2026高含量液体钙精选,强健骨骼提前预防骨质疏松 - 博客万
  • 【2026实测】直击Turnitin算法:英文论文AI率97%降至8%的4种高效方法
  • 【Matlab】MATLAB教程:Simulink示波器(Scope查看信号+仿真结果可视化)
  • FGA自动化助手:告别FGO重复刷本,每天节省3小时游戏时间
  • 2026年成都眼镜连锁店怎么选?TOP6深度评测报告给你答案! - 品牌推荐官方
  • GetQzonehistory完整指南:三步永久保存你的QQ空间回忆