<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[宏笋的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/ouyangxiaozi</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; ouyangxiaozi]]></copyright><item><title><![CDATA[SFINAE 检测惯用法（detection idiom）]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168126147</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168126147</guid><author>ouyangxiaozi</author><pubDate>Fri, 16 Oct 2026 11:56:19 +0800</pubDate><description><![CDATA[先来看一段代码：


这段代码是 C++ 里非常经典的 SFINAE 检测惯用法（detection idiom），用来在编译期判断一个类型  是否拥有可被  调用的成员函数 。下面逐层拆解。





二、逐行解析

1. 主模板  — 兜底默认值 







注意第一个模板参数  没有名字。这个“无名占位参数”是整个技巧的关键：它不是用来存储类型信息的，而是专门留出来给偏特化去“填充 SFINAE 表达式”的槽位。当偏特化匹配失败时，编译器回退到这个主模板，得到 （即“不具备 emplace_bac]]></description><category></category></item><item><title><![CDATA[RAII（Resource Acquisition Is Initialization）详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168118055</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168118055</guid><author>ouyangxiaozi</author><pubDate>Fri, 16 Oct 2026 10:48:16 +0800</pubDate><description><![CDATA[RAII 就是把「申请资源」放进构造函数、「释放资源」放进析构函数，借助栈对象必然析构这一机制，让资源生命周期和对象生命周期完全绑定，从而在不写一行手动清理代码的前提下，彻底杜绝内存泄漏、死锁和文件句柄泄漏。]]></description><category></category></item><item><title><![CDATA[深入理解std::declval的概念与用法]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168113846</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/168113846</guid><author>ouyangxiaozi</author><pubDate>Fri, 16 Oct 2026 10:33:02 +0800</pubDate><description><![CDATA[它只有声明、没有定义（所以永远不能被实际调用、不能被 odr-use）。它的返回值类型是T&&（或T&当编译器读到类的定义时，它不是把类当成"运行时才能造出来的东西"，而是立刻解析并归档成一份类型信息。// 声明编译器解析完这段后，会在符号表里给Vec符号表条目：Vec└─ 成员函数列表：├─ emplace_back : 参数 (double) → 返回 int, 无 const└─ size : 参数 () → 返回 int, 有 const这些信息在编译期就固定下来了，跟内存里有没有Vec。]]></description><category></category></item><item><title><![CDATA[C++指针悬空]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/167789547</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/167789547</guid><author>ouyangxiaozi</author><pubDate>Tue, 13 Oct 2026 10:52:44 +0800</pubDate><description><![CDATA[指针悬空（Dangling Pointer）是C/C++里最常见、也最难排查的内存错误之一，本质是：指针/引用本身还存在，但它指向的内存已经被释放、销毁或者失效了，此时再通过这个指针访问内存，就会触发未定义行为。指针本质就是一个存内存地址的整数变量：局部变量是分配在栈上的，函数返回时栈帧销毁，局部变量的内存会被自动回收：





种情况最坑：你测试的时候可能一直"正常工作"，因为刚释放的栈内存还没被其他函数调用覆盖，一旦后续调用其他函数、栈空间被复用，读到的就是随机垃圾值，bug极难复现。堆上分配的内存手]]></description><category></category></item><item><title><![CDATA[一款集结古今中外文学查阅与编辑的软件]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/164194291</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/164194291</guid><author>ouyangxiaozi</author><pubDate>Mon, 31 Aug 2026 00:05:33 +0800</pubDate><description><![CDATA[作为一名编程爱好者，花了近两年的业余时间，用QT开发了一款文学知识查阅与编辑软件（目前仅限windows系统和单机环境）。准确的说，它包括两个可执行文件，一个用于文学编辑（取名为“萃辞笺”），一个用于文学查询（取名为“萃辞观”），]]></description><category></category></item><item><title><![CDATA[QT 隐式共享/写时复制详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161837313</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161837313</guid><author>ouyangxiaozi</author><pubDate>Tue, 09 Jun 2026 18:42:51 +0800</pubDate><description><![CDATA[b = a;a[0] = 5;*i = 12;输出结果是：5 0 05 12 12是不是有些出人意料？为何会出现这种现象，原因是QVector是隐式共享（copy-on-write）的容器。以上代码中，b = a;并不会马上复制一份独立的数据。它只是让b和a共享同一块内部数据缓冲区。a和b共享同一个数据内存，i仍然指向那块内存。本质上指向内部数组，当修改a或b时，若发生写时复制（detach），迭代器可能失效。修改迭代器 i 就是用了隐式共享容器的 “裸指针式” 修改方式。]]></description><category></category></item><item><title><![CDATA[qss/css 样式中margin和padding的作用和区别]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161538235</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161538235</guid><author>ouyangxiaozi</author><pubDate>Sat, 30 May 2026 12:03:23 +0800</pubDate><description><![CDATA[这里的 contentsRect 是由 QWidget::contentsMargins 决定的，不是由 QSS 的 padding 决定的。用 layout 的 contentsMargins，不是控件样式表的 padding/margin。最容易混淆的是：Qt 里还有布局的 margin，这和 QSS 的 margin 不是一回事。先看两张图，分清“样式表盒模型”和“QWidget 几何系统”，后面就不容易混了。也就是说 margin 区域通常是“外部空白”，不是控件背景的一部分。]]></description><category></category></item><item><title><![CDATA[QTextDocument 功能和用法详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161537658</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161537658</guid><author>ouyangxiaozi</author><pubDate>Sat, 30 May 2026 11:43:58 +0800</pubDate><description><![CDATA[它本身不负责“像浏览器那样显示网页”，而是把文本、段落、图片、表格、列表、块级格式、字符级格式这些内容组织成一个可布局、可绘制、可编辑的文档树，然后交给布局器去排版，再交给绘制层输出到屏幕、打印机或任意 QPainter 目标。QTextDocument 相关类关系图，将QTextCursor、QTextBlock、QTextLayout、QAbstractTextDocumentLayout 一次串起来。更有效的是按职责完整梳理。它不是简单字符串，而是有行列、单元格、单元格格式、列宽约束的真实文档对象。]]></description><category></category></item><item><title><![CDATA[QT 实现多种格式的图标（包括png、ico、svg等）相互转换]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161265848</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161265848</guid><author>ouyangxiaozi</author><pubDate>Thu, 21 May 2026 00:22:55 +0800</pubDate><description><![CDATA[1、支持png、jpg、jpeg、ico、bmp、svg格式的图标相互转换格式（如下图所示）2、选取本地的图标后，可以显示图标的格式和尺寸，并有预览的功能；花了几个晚上，制作了一款多种格式的图标相互转换的小工具软件（3、可以选择需要转换的格式，可修改保存图标的路径和尺寸。源代码和打包的可执行文件见文章末尾。]]></description><category></category></item><item><title><![CDATA[QT 实现文件资源浏览器]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161219029</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161219029</guid><author>ouyangxiaozi</author><pubDate>Tue, 19 May 2026 11:33:03 +0800</pubDate><description><![CDATA[【代码】QT 实现文件资源浏览器。]]></description><category></category></item><item><title><![CDATA[C++ Coroutines（协程） 详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161186589</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161186589</guid><author>ouyangxiaozi</author><pubDate>Mon, 18 May 2026 10:56:25 +0800</pubDate><description><![CDATA[它不能像某些有栈协程那样在任意深层函数处直接切出去，只有在显式的 co_await、co_yield、co_return 这些语义点才能挂起。这段代码虽然没什么实际用途，但足以说明一件事：协程返回类型背后必须有一个 promise_type，编译器靠它决定如何构造、挂起、恢复和结束协程。让你看到 promise 怎么保存结果，handle 怎么 resume，co_await 怎么取值。也就是说，co_await 不是“等待某个固定类型”，而是等待“任何实现了 await 协议的对象”。]]></description><category></category></item><item><title><![CDATA[C++ 约束模板参数Concepts详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161143428</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161143428</guid><author>ouyangxiaozi</author><pubDate>Sat, 16 May 2026 15:50:24 +0800</pubDate><description><![CDATA[本文详细介绍Concepts 的概念和使用方法，让你彻底了解它]]></description><category></category></item><item><title><![CDATA[重写QWidget，实现QLineEdit的基本功能]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161120120</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161120120</guid><author>ouyangxiaozi</author><pubDate>Fri, 15 May 2026 18:48:27 +0800</pubDate><description><![CDATA[负责 text、cursor、selection、preedit、maxLength、echoMode。只有在你要完全自绘、自己控制光标、选区、输入法、焦点行为时，才建议直接继承 QWidget 重写。如果只是想改样式、限制输入、加按钮、改行为，优先继承 QLineEdit。负责 insert、delete、replace、undo、redo。把插入、删除、替换封装成命令，顺手就能加 undo/redo。负责边框、文本、选区、光标、占位文本、滚动偏移。负责键盘、鼠标、输入法、剪贴板、焦点和快捷键。]]></description><category></category></item><item><title><![CDATA[重写QWidget，实现弹出下拉菜单的功能]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161118898</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161118898</guid><author>ouyangxiaozi</author><pubDate>Fri, 15 May 2026 18:00:58 +0800</pubDate><description><![CDATA[QT 重写QWidget，实现以下功能：1、点击弹出下拉菜单，再次点击隐藏下拉框；2、弹出下拉框后，点击QWidget外，隐藏下拉框。]]></description><category></category></item><item><title><![CDATA[浮点数在计算机中存储格式详解]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161107124</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161107124</guid><author>ouyangxiaozi</author><pubDate>Fri, 15 May 2026 11:23:13 +0800</pubDate><description><![CDATA[在计算机里不是直接存“9.721 这几个十进制字符”，而是先转成二进制科学计数法，再按 IEEE 754 的。本文再讲解浮点数再计算机中存储的详细过程，比如double类型的9.721的整个转换和存储过程。要靠“乘 2 取整”反复展开，它不是一个有限二进制小数，所以会变成无限展开。，编译器会把它转换成“最接近 9.721 的那个 binary64 值”。这就是为什么浮点数经常会出现“看起来一样，底层并不完全相等”的现象。先按主流平台讲：在绝大多数 PC 和服务器上，C++ 里的。]]></description><category></category></item><item><title><![CDATA[深入了解浮点数在计算机中的存储方式和运算]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161105232</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161105232</guid><author>ouyangxiaozi</author><pubDate>Fri, 15 May 2026 11:09:43 +0800</pubDate><description><![CDATA[浮点数是用“符号 + 指数 + 尾数”按二进制科学计数法存的，能表示小数和很大范围，但很多值只是近似值；速度上不能绝对说谁更快，但通常整数更直接，浮点更复杂，而现代 CPU 上浮点加减乘也已经非常快。]]></description><category></category></item><item><title><![CDATA[C++ 标准库常用函数（sort, transform, accumulate, reduce等）]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088909</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088909</guid><author>ouyangxiaozi</author><pubDate>Fri, 15 May 2026 09:35:03 +0800</pubDate><description><![CDATA[下面这几个都是 C++ 标准库里非常常用的算法。先给你一个总图，便于建立感觉：如果只看本质，可以把它们分成三类：下面按“作用 + 用法 + 示例 + 注意点”讲。准备知识常用头文件：


示例里默认都用 。作用对区间内每个元素执行一次操作。你可以把它理解成：“把一个函数应用到每个元素上”。基本写法std::for_each(begin, end, func);示例 1：打印所有元素


输出：1 2 3 4 5示例 2：原地修改元素注意这里 Lambda 参数要写成引用。


输出：2 4 6 8 10什么]]></description><category></category></item><item><title><![CDATA[C++11使用chrono获取当前时间戳]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088683</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088683</guid><author>ouyangxiaozi</author><pubDate>Thu, 14 May 2026 18:14:57 +0800</pubDate><description><![CDATA[使用<chrono>的。注意防止编译器优化。多次测量取平均更可靠。对于复杂的性能分析，建议使用专门的 Profiler（如 perf, VTune）或 Google Benchmark 库。如果需要测量一个函数在真实环境中的耗时（包含 I/O、锁竞争等），可以保持函数原样测量；如果只测量算法 CPU 时间，需排除其他干扰，可以多次调用取最小值或使用配合高优先级线程。]]></description><category></category></item><item><title><![CDATA[C++ execution详解，附上代码示例]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088300</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161088300</guid><author>ouyangxiaozi</author><pubDate>Thu, 14 May 2026 17:54:41 +0800</pubDate><description><![CDATA[std::execution 的本质是：同一个标准算法，给它不同执行策略，就能用不同方式跑。]]></description><category></category></item><item><title><![CDATA[C++ string 和string_view的区别和用法]]></title><link>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161086896</link><guid>https://blog.youkuaiyun.com/ouyangxiaozi/article/details/161086896</guid><author>ouyangxiaozi</author><pubDate>Thu, 14 May 2026 16:47:14 +0800</pubDate><description><![CDATA[所以如果你把 string_view 直接丢给只接受 C 字符串的接口，就可能出问题。string_view 是 C++17 引入的，表示“对一段字符串的只读观察”。而 string_view 只是“知道长度”，不是“保证以 '\0' 截止”。这里放进容器里，通常应该存 string，而不是存 string_view。性能提升的前提是你真的只是读，不是存，不是改，不是跨生命周期保留。string_view 不拥有数据，所以它依赖原字符串继续存在。string 的 substr 会构造新字符串，通常会拷贝。]]></description><category></category></item></channel></rss>