C++享元模式进阶:从内存优化到状态拆分的实战指南
做C时间久了几乎都会碰到一个让人头疼的问题对象数量一多内存吃紧性能掉得莫名其妙。享元模式Flyweight Pattern就是专门治这个问题的套路之一但很多人对它的理解停留在“字符串驻留”或者“编辑器里共享字符图形”这种教科书案例上。这篇文章我想从实际工程的角度把C下享元模式的高级应用拆开聊一聊什么时候值得用、怎么正确拆分状态、怎么处理并发以及我在真实项目里踩过哪些坑。如果你正在做一个需要管理大量相似对象的后台服务、游戏场景、仿真程序或者单纯想知道“为什么一个看似简单的对象复用机制在C里会牵扯出生命周期、线程安全、内存碎片这么多问题”这篇文章值得你读完。我会用代码和实测思路说话不讲虚的。1. 为什么要用享元被对象数量压垮之前很多人的第一反应是直接用结构体数组不就行了确实如果对象的形状完全一致那么数组是最省事的方案。但现实里的对象往往带有大量重复数据又需要保留独立身份和各自的行为状态。这时候才轮到享元模式出场。1.1 一个具体的失控场景我先说一个我在某跨平台系统里遇到过的真实情况。系统里有一个相机标定模块每帧会生成几千个特征点对象每个对象都带着一大串配置信息算法版本号、相机内参、畸变系数、标定板参数、缓存通道标识等。这些数据在整个运行周期内几乎不变但每个特征点对象都完整拷贝了一份。那个模块上线没多久内存占用就飙到几个GBGC暂停也变得很反常。我用性能剖析工具抓了一下发现大量时间花在对象的初始化、成员变量赋值和内存分配上。问题很清楚几千个对象里真正随帧变化的信息可能只有坐标、时间戳、置信度这几个字段剩下几百字节的“配置尾巴”全部是重复的。这就是享元模式最典型的应用前提大量相似对象其中一部分状态是共享的、不变的另一部分状态是独立的、随场景变化的。前者叫内部状态Intrinsic State后者叫外部状态Extrinsic State。享元模式要做的事情就是把内部状态抽出来做成共享对象把所有外部状态从对象里挪出去让不同的调用方根据自己的上下文临时组合。1.2 享元模式解决的问题边界不过我得先说清楚享元不是万能的。它的收益来自于两个前提一是对象实例数量足够大大到“每个对象保存全量字段”的内存开销不可忽略二是内部状态在所有实例里真正重复而不是各自不同。如果对象的唯一性很强比如每个实例都有大量独有数据强行共享反而会引入状态管理复杂度代码更难维护。另外C里对象是有值语义的如果你只是想让几个轻量对象共享一大块数据不一定非要套“模式”这个名字可能一个std::shared_ptrconst Config就解决了。享元模式的价值在于它把所有共享逻辑收拢到一个工厂里让调用方不需要关心对象从哪来、生命周期怎么管理。提示判断是否引入享元先做一个粗略估算对象数量 × 重复字段大小如果这个值超过内存预算的10%以上再考虑共享否则先别急着引入模式避免过度设计。2. C里实现享元的三个关键选择模式本身的概念不难难的是在C这个语言环境下怎么落地。别急着写抽象基类和工厂接口先想清楚下面三个问题。2.1 内部状态与外部状态怎么切这是整个模式的核心决策也是最容易出错的地方。我的经验是先列字段再分类最后看“变化频率”和“共享价值”。变化频率是第一个筛子。每帧都变、每个实例都不同的字段比如坐标、角度、ID理论上应该归为外部状态。生命周期内几乎不变、所有实例都相同的字段比如渲染管线类型、算法配置、物理参数可以归为内部状态。共享价值是第二个筛子。有些字段虽然不变但每个对象只保存一份最小的枚举或短字符串共享它的内存收益很小。这时候不要硬塞进享元对象里因为每次访问都要通过间接指针反而破坏缓存友好性。我用一个粒子对象举个例子。假设一个粒子有位置、速度、颜色、纹理句柄、混合模式、生命周期、出生时间这些字段。如果粒子数量只有几百全放一起没问题。但如果是几万粒子每个粒子都保存一份“纹理句柄混合模式”就太浪费了。正确做法是把纹理句柄和混合模式提炼成一个ParticleRenderConfig放进共享池把位置、速度、生命周期、出生时间保留在粒子数组里。struct ParticleRenderConfig { TextureHandle texture; BlendMode blend; bool enableAdditive; }; struct Particle { float x, y, z; float vx, vy, vz; float life; float birthTime; const ParticleRenderConfig* config; // 指向共享对象 };这里有个细节config用原始指针还是shared_ptr如果ParticleRenderConfig由全局池管理生命周期比所有粒子都长原始指针就够用。如果池里的配置可能动态销毁那就得用shared_ptr或者带索引的池化存储。这个问题我在后面“踩坑”部分再展开。2.2 共享存储与管理方式怎么选享元对象通常需要通过工厂获取。工厂内部维护一个注册表按某种Key去查找已有实例找到就返回复用找不到就创建新的并登记。C里实现这个注册表最常见的三种做法做法一static字典 懒加载。简单直接适合单线程或低频访问。缺点是并发访问要加锁而且static对象销毁顺序是个隐患如果在程序退出阶段还有线程访问可能踩到已析构的静态对象上。class RenderConfigRegistry { public: static const ParticleRenderConfig get(size_t id) { static std::unordered_mapsize_t, std::unique_ptrParticleRenderConfig cache; auto it cache.find(id); if (it cache.end()) { auto config std::make_uniqueParticleRenderConfig(loadConfigById(id)); it cache.emplace(id, std::move(config)).first; } return *(it-second); } };做法二独立池对象。把注册表设计成一个普通类生命周期由上层模块控制。这样更容易做测试也能配合依赖注入。很多服务端程序习惯把这类池放在模块上下文里避免全局静态状态。做法三shared_ptrweak_ptr缓存。允许缓存对象在不再被使用时自动销毁避免长时间占内存。适合共享对象比较大、数量不固定、使用频率不均的场景。class FontGlyphCache { public: std::shared_ptrconst Glyph getGlyph(uint32_t codepoint, int size) { auto key std::pairuint32_t, int{codepoint, size}; std::lock_guard lock(mutex_); auto it cache_.find(key); if (it ! cache_.end()) { if (auto glyph it-second.lock()) { return glyph; } } auto glyph std::make_sharedGlyph(rasterize(codepoint, size)); cache_[key] glyph; return glyph; } private: std::mutex mutex_; std::unordered_mapCacheKey, std::weak_ptrconst Glyph, KeyHash cache_; };这个做法我特别喜欢因为它把“共享”和“回收”做到了动态平衡。但要注意weak_ptr无法完全避免重复创建如果一个对象被所有使用者释放缓存里只剩weak_ptr下次访问还会重新创建。如果业务上极少重复创建这种方式没问题如果对象创建成本很高建议改成强引用缓存加上定期清理策略。2.3 线程安全与并发访问享元模式放到多线程环境里麻烦才真正开始。最需要警惕的是共享对象本身是只读的但获取共享对象的过程是写操作。缓存表的插入、删除都会改变容器结构必须加锁。但加锁粒度不能太粗。以字体缓存为例如果你在整个光栅化过程中都持锁那每个线程都会排队等光栅化性能直接崩。正确做法是锁只保护缓存查找和插入光栅化在锁外完成。更高级一点可以考虑用读写锁读多写少的场景下std::shared_mutex能让多个线程同时查找。不过shared_mutex本身有开销如果临界区极短、抢锁频率极高普通mutex反而更快。这个需要通过实测验证不能拍脑袋。另一个并发陷阱是“共享对象的初始化”。比如一个全局配置享元第一次创建需要加载文件、解析参数耗时很长。如果多个线程同时触发创建可能会重复加载。解决思路是双检锁Double-Checked Locking或者在工厂里用std::call_once但更稳妥的做法是启动阶段预加载把创建过程放在单线程里完成运行阶段只读访问。class ConfigFlyweightFactory { public: static const AppConfig get(const std::string version) { std::shared_lock readLock(mutex_); auto it configs_.find(version); if (it ! configs_.end()) { return *(it-second); } readLock.unlock(); std::unique_lock writeLock(mutex_); // 二次检查防止另一个线程已经创建 it configs_.find(version); if (it configs_.end()) { configs_[version] std::make_sharedAppConfig(load(version)); } return *(configs_[version]); } private: static std::shared_mutex mutex_; static std::unordered_mapstd::string, std::shared_ptrconst AppConfig configs_; };注意共享对象应该以const暴露。把内部状态暴露成普通引用等于开放了修改入口一旦某个调用方改了共享字段所有使用该享元的对象都会受影响而且这种问题极难追踪。3. 高级应用当共享不再只是“省内存”教科书里的享元应用是“文档里的字符共享字形数据”这确实是经典。但实际工程里享元的应用场景要丰富得多而且很多时候并不是直接为了省内存而是为了提升缓存命中率、减少初始化开销、简化状态管理。3.1 游戏场景中的粒子系统与瓦片地图游戏里物体会爆炸式增长最典型的就是粒子系统。我曾经写过一个技能特效系统单次技能会生成上万个粒子。如果每个粒子都保存一份完整材质数据内存开销和初始化成本都扛不住。用享元把材质、混合模式、深度测试策略抽成共享配置后粒子对象缩到只有几十字节可以整块放进连续内存里遍历时CPU缓存命中率提升非常明显。瓦片地图也是经典场景。一个大地图可能有几十万块瓦片但瓦片类型通常只有几十种。每块瓦片只需要存一个tileTypeId详细的地形数据、纹理路径、碰撞属性都由享元池提供。这种设计不仅省内存还让“修改某种地形的整体属性”变得异常简单改池子里那一份对象就行不用遍历整个地图。关键优化点在于享元对象本身用const数组存储瓦片对象只存枚举值或索引访问时通过索引取配置。这样比用一个指针更省内存还避免了指针间接跳转。如果用std::vectorint8_t存瓦片类型整个地图可以做到按块加载性能表现非常稳。3.2 文本排版中的字形复用字体光栅化是一个重操作特别在中文、日文这种字符集庞大的场景里。如果你每渲染一个字符都重新光栅化一次性能会惨不忍睹。合理做法是把“字体文件加载后的原始轮廓数据”作为内部状态把“具体像素大小的位图缓存”作为另一层共享对象两者组合成完整的字形享元。我之前优化过一个文本渲染引擎。初始实现里每个界面文本对象都持有自己的字形缓存结果打开多个页面后内存直线上升。后来我引入全局字形池按(字体ID, 字符, 字号, 抗锯齿模式)作为Key共享位图整个应用的显存占用下降了约40%。这里有个细节缓存Key不能只算字符否则不同字体的同一个字会互相覆盖也不能漏掉缩放系数否则小字号和大字号会共用低清位图渲染效果发虚。3.3 连接池与请求上下文服务端程序里数据库连接池、网络连接池、线程池本质上都带有享元思想的影子。连接对象本身是可复用的但连接上的临时状态当前事务、当前查询属于外部状态不能混在共享对象里。很多连接泄漏问题的根因就是把“正在使用的状态”写进了连接对象本身归还后没有清理干净下一个请求拿到了脏状态。我曾经排查过一个诡异的服务端bug某个数据库查询偶尔会带上上一个请求的过滤条件。最后发现是连接池里的连接对象保存了lastStatement字段归还池时没有重置。修复方式是把语句参数作为外部状态传入查询方法连接对象只负责底层传输。这就是享元思想在另一个维度的体现共享对象必须无状态或者状态只能被显式地在使用前设置、使用后清理。3.4 常用数据的只读缓存除了上面这些场景还有一种更抽象的使用方式把“计算成本高、结果可复用”的数据作为享元缓存。比如AI算法里的特征向量、几何运算里的预计算矩阵、编译器里的符号表条目都可以放入共享池用const方式暴露。这里与普通缓存的区别在于普通缓存通常存的是“计算结果”访问一次之后几乎不再变化享元强调的是“按身份共享”即相同的Key对应同一个实例。两者可以结合比如把“模型ID”映射到“模型特征数据”同一个模型ID永远拿到同一个对象所有线程共享同一个只读特征集避免了重复加载和重复计算。实测在模型加载次数较多的服务里这种设计能把单次请求的模型准备阶段从几十毫秒降到微秒级。4. 实测维度收益与代价都要量化说再多理论不如给出可执行的实际对比方案。我建议你在引入享元之前先做一个很小的性能基线测试把收益和代价量化。别只盯着内存数字还要看CPU访问模式、分配次数、锁竞争。4.1 内存收益怎么统计统计方法很直接。先计算“朴素版本”的内存占用假设每个对象完整保存所有字段用sizeof(Object) * N估算再实现享元版本后用sizeof(SharedObject) sizeof(ExternalState) * N估算。两条曲线交叉点就是享元模式的“回本线”。以我之前做的特征点系统为例。特征点对象原始结构体约400字节每帧5000个就是2MB。重构后共享配置约4KB外部状态对象降到64字节总内存约320KB。内存收益约85%而且这个收益随对象数量线性放大。如果你有接口能测量进程常驻内存例如/proc/self/statm建议在20分钟压力测试后抓两版数据对比。除了容量还要看内存分配次数。共享对象创建一次之后全是复用。用malloc钩子或tcmalloc的统计接口能看到分配次数明显下降。分配次数少内存碎片自然少这在长时间运行的服务里非常有价值。4.2 性能影响和缓存友好性享元模式有可能带来负面性能因素因为访问共享对象——经由指针间接跳转——会打乱数据局部性。上面粒子系统的例子中如果config是裸指针每个粒子在遍历时都要多一次解引用。但如果配置是连续数组存储的所有粒子共享同一个配置指针它们在L2缓存里几乎不会失效相反如果每个粒子各存一份纹理句柄虽然少了指针跳转但粒子数组体积变大缓存命中率下降遍历性能反而更差。我建议做两种实现各跑一百万次循环分别统计耗时。不要只看平均值要看P95和最大值防止偶发抖动的假象。还要注意如果你的外部状态很小比如几个float那放进数组里直接传值比通过享元指针间接访问更快只有当共享部分很大、数量很多时享元的间接访问代价才划算。4.3 什么时候不值得用不是说看到了重复数据就要用享元。如果对象数量只有几十个重复字段只有几个字节引入工厂、锁、生命周期管理带来的复杂度和代码阅读成本远大于那几十字节的收益。还有种情况你的对象生命周期极短创建后立即销毁共享池反而会把它长期留存在缓存里造成内存上限失控。再有如果对象需要频繁修改内部状态比如一个配置文件在运行期会变享元就很尴尬。共享对象一旦可变所有使用者都必须处理变更通知这个复杂度会指数级上升。保持内部状态不可变是享元实现里最省心的约束。如果确实需要动态更新建议用“版本号重建对象”的方式而不是直接改共享实例。提示判断要不要用享元我习惯用一个“3倍原则”对象数量预计超过3000个、重复字段大小预计超过300字节、生命周期超过3分钟三条里中两条才认真考虑享元模式。5. 实战中我踩过的坑享元模式看起来简单但放到真实工程里坑一个接一个。我下面说的这几个都是我实际踩过、也帮别人擦过屁股的问题。5.1 外部状态引用导致的生命周期悬垂这是最常见的坑。我见过有人把享元对象的指针存到外部状态对象里外部状态对象被拷贝、移动后原来的指针还指向旧地址。比如用std::vector存粒子粒子扩容时数据会被移动如果粒子内部持有的是“指向自己的指针”或“指向兄弟数据的指针”扩容后就悬垂了。正确的做法是外部状态不应该持有指向自己的引用只能持有指向共享池的指针。如果一定要保存相对数据用索引而不是指针。比如在粒子数组中不存ParticleRenderConfig* config而是存int configIndex访问时查表。这样即使数组移动索引依然有效。索引还天然支持序列化和网络传输方便很多。5.2 共享对象被意外修改内部状态必须设为const这不只是规范上的建议是安全底线。我在一个缓存模块里吃过亏两个模块共用一个配置享元其中一个模块为了存临时数据往配置对象里塞了一个调试标记。结果另一个模块读取配置时拿到了被篡改的调试标记导致行为异常。因为是偶发问题排查了很久才发现是共享对象被写。实在需要某个模块持有额外信息就把它放进该模块自己的外部状态里不要污染共享对象。如果希望优雅地防止修改可以提供只读接口内部存储用const字段加私有构造函数外部无法直接改。5.3 工厂变成性能瓶颈享元工厂如果每次都加锁、查哈希表、做动态分配在高频调用下会变成新的热点。我见过一个极端案例每次渲染一个字符都要访问字形工厂结果工厂里的std::unordered_map查找和锁竞争成了整个渲染流程的最大瓶颈。解决方案有几个。第一缩小锁粒度把共享池按类型拆分成多个小池各自独立加锁。第二使用更快的查询结构很多场景下Key是有规律的用数组或FlatHashMap比无序表更快。第三减少调用次数对于一批粒子、一批字符可以批量获取共享对象而不是每个都查表。如果Key是整数且范围不大直接用std::vectorstd::shared_ptrconst T按索引访问连哈希都不用。如果Key是字符串优先考虑字符串驻留后再用整数ID映射能避免每次都算字符串哈希。这些细节在压力测试里差别很大。6. 个人心得与建议做享元模式这么久我个人最大的体会是模式本身不是重点重点是你能不能把“内部状态”和“外部状态”这条线画得足够清楚。这条线画得好后续的内存管理、并发控制、扩展性都会非常顺畅画得模糊代码会变成一团互相牵连的状态网比不用享元还难维护。另一个实用建议是上手时先从最简单的共享对象做起不要一上来就搞weak_ptr、读写锁、分布式共享那一套。先用static缓存加裸指针跑通流程验证收益后再逐步加并发保护。过度设计是享元落地的大敌因为这个模式的核心价值是“省内存、简化对象”如果你的实现本身复杂到需要花大量时间维护那就本末倒置了。最后分享一个小技巧给享元对象加一个“身份ID”字段查问题的时候特别好用。无论从哪个路径获取到享元打印ID就能知道是不是同一个实例能快速定位“共享对象被改”和“缓存Key错误”这类问题。我后来在新项目里都会保留这个字段虽然它理论上不属于内部状态的一部分但作为调试信息价值远超那几字节成本。

相关新闻

SpringBoot+Vue旅游网站全栈实战:从数据库设计到部署联调

SpringBoot+Vue旅游网站全栈实战:从数据库设计到部署联调

很多做毕业设计和课程设计的朋友,一听到“旅游网站”这种题目,第一反应就是满大街的CRUD,感觉没什么技术含量。但作为一个带过不少项目的开发者,我想说这种题目恰恰是最能拉开差距的。一个看似平平无奇的旅游文化网站,…

2026/10/15 22:01:16 阅读更多 →
2026年专业AI工具选型策略:从跑分到工作流适配的关键维度

2026年专业AI工具选型策略:从跑分到工作流适配的关键维度

每年年初都会有人问我同一个问题:今年该用哪套AI工具?早几年我还乐此不疲地列长清单、做对比表,后来发现一个尴尬的事实——对方照着清单挨个试用,折腾一晚上,最后又回到了原来的工作方式。问题多半不在工具本身&#…

2026/10/15 22:01:16 阅读更多 →
PTA理论考C语言判断题解析:从预处理到switch的避坑指南

PTA理论考C语言判断题解析:从预处理到switch的避坑指南

简介:面向PTA平台C语言理论考试整理的Word题册,集中收录HW02、HW03两大部分的选择与判断题。内容紧扣基础语法:编译预处理指令、main函数唯一性、语句分号规则、变量声明顺序、单目运算符操作数、scanf/printf格式匹配、赋值与算术运算符优先…

2026/10/15 22:01:16 阅读更多 →

最新新闻

Android-WizardPager状态保存完全指南:save()/load()让向导流程完美恢复现场

Android-WizardPager状态保存完全指南:save()/load()让向导流程完美恢复现场

示例工程移动开发 【免费下载链接】Android-WizardPager Android pager-style wizard flow sample code 项目地址: https://gitcode.com/gh_mirrors/an/Android-WizardPager 点击查看 免费下载 Android-WizardPager 是一个基于 ViewPager 的向导式(wiza…

2026/10/15 22:44:11 阅读更多 →
HTTPS环境下SSE实时推送:EventSource与Nginx配置避坑指南

HTTPS环境下SSE实时推送:EventSource与Nginx配置避坑指南

最近在做一个运营后台的实时消息推送需求:服务端有新的订单状态变更、告警消息,需要第一时间推到浏览器页面上,延迟还要控制在秒级以内。技术选型的时候我在 WebSocket 和轮询之间纠结了一阵,最后落到了 JavaScript 的SSE&#xf…

2026/10/15 22:44:11 阅读更多 →
PyTorch到TensorFlow模型转换:ONNX链路避坑全指南

PyTorch到TensorFlow模型转换:ONNX链路避坑全指南

前段时间我把一个 PyTorch 训练的语义分割模型送到生产环境,目标推理框架是 TensorFlow Serving,中间必须走一遍 pytorch → onnx → tensorflow 的转换链路。一开始我以为就是两行命令的事,结果前后折腾了两周,踩的坑数量远超预期…

2026/10/15 22:44:11 阅读更多 →
tfsec 规则详解:aws-athena-no-encryption-override——强制 Athena 工作组加密配置,防止客户端覆盖

tfsec 规则详解:aws-athena-no-encryption-override——强制 Athena 工作组加密配置,防止客户端覆盖

应用安全SASTIaC 【免费下载链接】tfsec Tfsec is now part of Trivy 项目地址: https://gitcode.com/gh_mirrors/tf/tfsec 点击查看 免费下载 本篇技术指南围绕 tfsec 内置检查规则 aws-athena-no-encryption-override 展开,讲解如何在 Terraform 中通…

2026/10/15 22:44:11 阅读更多 →
商场客户分群实战:从RFM到动态标签的三层漏斗模型

商场客户分群实战:从RFM到动态标签的三层漏斗模型

1. 项目概述:为什么商场客户分群不是“贴标签”,而是生意的导航仪你走进一家商场,电梯口立着电子屏,滚动播放“本层女装区今日会员专享85折”;收银台小票底部印着一行字:“您已连续3次购买儿童辅食&#xf…

2026/10/15 22:44:11 阅读更多 →
GEE交互式碳固存潜力地图:土壤属性评估与优先补碳地块筛查

GEE交互式碳固存潜力地图:土壤属性评估与优先补碳地块筛查

做区域碳汇潜力摸底的时候,我最头疼的往往不是报告怎么写,而是怎么让决策者一眼看懂“哪些地块值得优先补碳”。单看一张土壤有机碳含量图不够——含量低的地方可能受限于砂质、干旱,实际提升潜力很小;含量高的湿地和林地又可能已…

2026/10/15 22:43:10 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →