<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[InvictusCoder的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/InvictusCoder</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; InvictusCoder]]></copyright><item><title><![CDATA[C++ stack 全面解析与实战指南]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169503049</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169503049</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:49:01 +0800</pubDate><description><![CDATA[std::stack是 C++ 标准库里的容器适配器（container adaptor），不是容器。它把某个底层容器的接口「收缩」成后进先出（last in, first out，LIFO）的三个动作：压栈、看栈顶、弹栈。std::stack没有迭代器，也不能用下标访问中间元素；它的pop()不返回被弹出的值。典型误解还有「std::stack默认用实现」。标准规定的默认底层容器是std::deque，不是vector。选择deque是因为它两端操作都是常数时间，且压栈不会导致已有元素的引用整体失效；]]></description><category></category></item><item><title><![CDATA[C++ Sqlite3的使用方法]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502957</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502957</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:48:29 +0800</pubDate><description><![CDATA[SQLite 是一个嵌入式关系数据库：没有独立服务进程，整个数据库就是一个文件，库本身以 C 接口提供。C++ 项目使用它通常有两种方式：直接调用sqlite3.h暴露的 C API，或者使用某个 C++ 封装库。前者没有额外依赖、行为最可控，也最能看清资源管理的边界，适合先把原理弄明白。初学者最容易踩的坑是把 SQL 字符串和用户输入拼接起来。这不仅能构造出语法错误，还会带来 SQL 注入风险。]]></description><category></category></item><item><title><![CDATA[C++ spdlog日志库示例详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502869</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502869</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:47:57 +0800</pubDate><description><![CDATA[spdlog 是 C++ 生态里使用很广的日志库，特点是头文件友好、接口短、基于 fmt 的格式化、支持同步与异步、支持轮转文件。它的核心价值不是「能打印」，而是把日志级别、输出目标、格式、线程安全、文件生命周期这几件事拆成可组合的部件，让程序在开发期和运行期都能调整行为，而不必在每个调用点写条件判断。典型误解有三个。第一，以为 spdlog 是标准库的一部分——它不是，需要单独引入并链接（或使用 header-only 模式）。第二，以为这类全局函数永远可用——它们走的是「默认 logger」，在。]]></description><category></category></item><item><title><![CDATA[C++ sort排序函数用法详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502772</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502772</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:47:25 +0800</pubDate><description><![CDATA[std::sort定义在中，是 C++ 最常用的排序算法。它的接口只有两个核心参数——首迭代器和尾后迭代器——再加一个可选的比较器。看似简单，但围绕它有大量误用：比较器写成<=、对std::list调用、以为排序稳定、在比较器里修改元素。这些错误有的直接编译失败，有的则是未定义行为（undefined behavior, UB），运行时才以奇怪的方式暴露。先把几个事实说清楚。std::sort要求随机访问迭代器，因此std::array、普通数组、std::deque可以用，std::list。]]></description><category></category></item><item><title><![CDATA[C++ sort排序之降序、升序使用总结]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502661</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502661</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:46:45 +0800</pubDate><description><![CDATA[std::sort声明在中，默认按operator<升序排列。想降序，可以传，也可以传一个返回a > b的 lambda。看起来只是换个比较符号，但这里藏着 C++ 排序最常见的未定义行为：比较器不满足严格弱序严格弱序要求比较关系满足四条：非自反（comp(x, x)必须为假）、非对称（comp(x, y)为真则comp(y, x)为假）、传递（comp(x, y)且comp(y, z)则comp(x, z)）、等价关系传递。写成a <= b或a >= b就违反了非自反，std::sort。]]></description><category></category></item><item><title><![CDATA[C++ sizeof 运算符]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502560</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502560</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:46:09 +0800</pubDate><description><![CDATA[sizeof是 C++ 里少数几个"看起来像函数、实际是运算符"的东西：它不需要头文件，不加括号也能用，返回类型是，而且在绝大多数情况下结果在编译期就确定了。很多人对它的误解集中在两点：一是以为它会像函数一样求值参数，写出后担心i被加一；二是把它当成"求长度"的通用工具，对数组用得很顺，换成指针或就得到完全不符合预期的数字。sizeof这个类型或这个表达式的结果类型，在内存中占多少个字节。它不知道数组里存了几个元素，也不知道字符串有多长，更不知道结构体里哪个成员"有用"。]]></description><category></category></item><item><title><![CDATA[C++ set的使用方法详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502462</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502462</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:45:37 +0800</pubDate><description><![CDATA[std::set是 C++ 标准库中的有序关联容器：它保存一组互不相同的元素，并按比较器维持顺序。需要"去重 + 有序 + 快速查找"时，它往往是最直接的选择。元素一旦进入容器，位置就由比较器决定，因此标准不允许通过迭代器修改键值——set的迭代器解引用得到的是 const 引用，这一点与完全不同。初学者最常见的误解有三个：把set当成"会自动去重的数组"，却忽略了它会按operator<排序；以为insert返回void，拿不到"是否插入成功"的信息；以为遍历顺序就是插入顺序。实际上insert。]]></description><category></category></item><item><title><![CDATA[C++ set 与 multiset 容器使用指南：关联式容器入门]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502375</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502375</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:45:02 +0800</pubDate><description><![CDATA[std::set和是标准库中的有序关联容器：元素按比较规则自动排序，查找、插入、删除的复杂度是对数级。set要求元素唯一，multiset允许重复。很多教程把这条差别一笔带过，但由此衍生出的接口差异（insert的返回值、erase的语义、count的结果）才是实际写代码时最容易出错的地方。常见误解有四个。第一，以为set的查找是常数时间；常数时间的是无序容器set是对数时间。第二，以为可以像vector一样通过迭代器修改元素；set的迭代器解引用得到的是const引用，元素不可原地修改，否则会破坏排序。]]></description><category></category></item><item><title><![CDATA[C++ random_shuffle()方法案例详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502270</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502270</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:44:28 +0800</pubDate><description><![CDATA[在 C++14 已被弃用，C++17 起已从标准库中移除。也就是说，在 C++17 或更新的标准下写会直接编译失败。网上大量旧教程仍把它当作标准写法，照抄会踩坑。现在应当使用，并显式传入一个均匀随机位生成器（uniform random bit generator, URBG）。被移除的原因主要有两个。第一，它的无参重载通常依赖std::rand，随机源的质量和实现相关，调用方无法控制。第二，它的带函数对象重载要求该函数返回[0, n)内的值，约束不直观，容易写出越界或分布不均的代码。]]></description><category></category></item><item><title><![CDATA[C++ Queue队列类模版实例详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502174</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502174</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:43:54 +0800</pubDate><description><![CDATA[队列(queue)是先进先出(first in, first out, FIFO)的容器:元素从一端进入,从另一端离开。C++ 标准库提供了std::queue,但它是容器适配器(container adapter),默认以std::deque为底层,只暴露pushpopfrontbackemptysize等少数接口。很多教材要求「自己实现一个队列类模板」,目的不是重复造轮子,而是理解模板类怎么写、FIFO 如何用循环缓冲实现、以及异常安全与对象生命周期如何兼顾。最常见的误解是把pop()]]></description><category></category></item><item><title><![CDATA[C++ Qt开发之关联容器类使用方法详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502088</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169502088</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:43:19 +0800</pubDate><description><![CDATA[它们与标准库的std::mapstd::set解决同类问题，但接口、迭代器风格和底层行为都有差异。Qt 项目里通常优先用 Qt 容器，因为它们与QStringQList等类型配合更顺，也支持 Qt 的隐式共享机制。需要先说明：Qt 是第三方框架，不是 C++ 标准库的一部分。本文的示例需要 Qt 5 或 Qt 6；Qt 6 要求 C++17，Qt 5 对 C++ 标准的要求随版本不同。]]></description><category></category></item><item><title><![CDATA[C++ QT QThread启动、停止、暂停和恢复的实现]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501981</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501981</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:42:44 +0800</pubDate><description><![CDATA[在 Qt 里做后台任务，QThread 是最常被提到的类，但它也是最容易被误用的类之一。很多教程一上来就让大家继承 QThread、重写run()，然后把业务槽函数也写在子类里，于是出现「线程启动了，槽却在主线程执行」的怪现象。这不是 Qt 的 bug，而是对象线程亲和性（thread affinity）在起作用：QThread 对象本身属于创建它的线程，只有run()函数体是在新线程里跑的。另一个常见误解是「暂停就是」或者「暂停就是挂起线程」。]]></description><category></category></item><item><title><![CDATA[C++ qsort函数排序与冒泡模拟实现流程详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501891</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501891</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:42:12 +0800</pubDate><description><![CDATA[qsort是 C 标准库提供的通用排序函数，声明在<cstdlib>（C 语言里是<stdlib.h>它最大的特点是「类型无关」：通过void*接收任意数组的首地址，用元素字节数告诉它每个元素多大，再通过一个函数指针回调比较逻辑。C++ 标准库把它们一并纳入，所以在 C++ 里写std::qsort是合法的。标题里的「冒泡模拟实现」不是指用冒泡排序去替代qsort的内部算法，而是指按qsort的接口约定，用冒泡排序实现一个同签名的函数——同样的void* base。]]></description><category></category></item><item><title><![CDATA[C++ Protobuf的学习使用指南]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501800</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501800</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:41:39 +0800</pubDate><description><![CDATA[Protocol Buffers（下称 protobuf）是 Google 开源的结构化数据序列化方案：你用一个.proto文件描述消息结构，protoc编译器据此生成目标语言的类，程序里用这些类填充数据、序列化成二进制、再在网络另一端反序列化。它常见的用途是 RPC 的载荷、跨进程通信、持久化存储，以及需要长期兼容演进的数据格式。初学者对 protobuf 的误解集中在两处。]]></description><category></category></item><item><title><![CDATA[C++ POSIX API超详细分析]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501627</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501627</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:40:36 +0800</pubDate><description><![CDATA[POSIX（Portable Operating System Interface）是一套C 语言接口标准，不是 C++ 标准的一部分。它规定了openreadwritefork这些函数的语义，也规定了<unistd.h><fcntl.h>这些头文件里该有什么。C++ 代码当然可以直接调用它们——头文件里的声明本身就带extern "C"，所以不存在名字修饰（name mangling）不匹配的问题。POSIX 不是「Linux API」。Linux 基本符合 POSIX，又加了一大堆自己的扩展（]]></description><category></category></item><item><title><![CDATA[C++ pair的基本用法总结整理]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501534</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501534</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:40:04 +0800</pubDate><description><![CDATA[std::pair是把两个值捆在一起的最小工具，定义在<utility>中。它最常见的用途是让函数返回两个结果、作为关联容器的元素类型、以及在排序时把"键 + 值"当成一个整体比较。常见误解是"pair是一个小类，随便用用就行"。std::map的元素类型是，键是 const 的，不能通过first修改；会对参数做类型退化，传引用不会保留引用；结构化绑定不加会得到一份拷贝。本文按创建、访问、比较、典型用途的顺序讲pair，并说明它和std::tuple的关系。是两个公开成员firstsecond。]]></description><category></category></item><item><title><![CDATA[C++ pair方法与vector方法案例详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501436</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169501436</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:39:33 +0800</pubDate><description><![CDATA[std::pair是标准库最简单的组合类型：把两个值绑在一起，用first和second访问。它常出现在三个地方：作为std::map的元素类型、作为函数返回多个值的载体、作为的元素来保存键值对序列。则是动态数组，几乎每个 C++ 程序都会用到。把两者结合成，就得到了一个「可按任意规则排序的轻量映射」——它不像std::map那样自动按 key 排序，但允许按 value 排序、允许重复 key、内存连续。常见的误解是「就是mapmap按 key 有序、key 唯一、查找 O(log n)；]]></description><category></category></item><item><title><![CDATA[C++ LeetCode542矩阵示例详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169500702</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169500702</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:35:11 +0800</pubDate><description><![CDATA[LeetCode 第 542 题「01 矩阵」的要求是：给定一个只含 0 和 1 的矩阵，返回一个同样大小的矩阵，其中每个位置的值是「该位置到最近的 0 的距离」。距离按上下左右四个方向计算，每走一格算一步。这道题最容易想到的做法是「对每个 1 做一次广度优先搜索，找到最近的 0」。这个思路正确，但复杂度是 O((mn)²)：矩阵里有 O(mn) 个 1，每个都要搜索几乎整个矩阵。数据量一大就会超时。更合适的做法是把所有 0 同时作为起点，做一次多源广度优先搜索。]]></description><category></category></item><item><title><![CDATA[C++ IO流详解之标准IO、文件IO与字符串IO实战]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169500544</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169500544</guid><author>InvictusCoder</author><pubDate>Fri, 30 Oct 2026 05:34:19 +0800</pubDate><description><![CDATA[C++ 的输入输出是一套基于流（stream）的抽象。相比 C 的printfscanf，它的优势是类型安全和可扩展性 —— 你可以为自己的类型定义operator<<，让它像内置类型一样被输出。流的内部状态是一台小状态机cin >> n;为什么s是空的？为什么读文件循环多做了一次？为什么输入一个字母后，后面所有cin >>全失败？为什么读二进制文件总是差几个字节？流状态位（stream state flags）。本文按"标准 IO → 文件 IO → 字符串 IO"的顺序讲清楚。内容。]]></description><category></category></item><item><title><![CDATA[Python线程详解]]></title><link>https://blog.youkuaiyun.com/InvictusCoder/article/details/169374172</link><guid>https://blog.youkuaiyun.com/InvictusCoder/article/details/169374172</guid><author>InvictusCoder</author><pubDate>Thu, 29 Oct 2026 02:45:13 +0800</pubDate><description><![CDATA[多线程（multithreading）是 Python 里最容易被高估、也最容易被误解的特性的组件之一。常见的第一层误解是「多线程等于多核并行、所以一定更快」；第二层误解是「既然 CPython 有 GIL，那多线程干脆没用」。这两句话都不成立。线程真正解决的问题是并发（concurrency）：让程序在等待某件事（网络响应、磁盘读写、用户输入）的时候，能腾出手去干别的。它从来不是并行（parallelism）意义上的「同时算」。]]></description><category></category></item></channel></rss>