一句话核心结论 :POCO Foundation 18 个子模块、200+ 个类,真正决定你日常开发体感的,只有”三件套”——智能指针、字符串、异常 。本文用 2300 行 C++ 代码 + 20 张对比表 + 8 张架构图,把这套”工业级 STL 补完计划”全部拆开讲透。
系列导航 # 文章 状态 1 POCO 是什么?为什么我决定用 C++ 重写整个网关 ✅ 已发布 2 本文:Foundation 核心三件套 ✅ 已发布 3 Foundation 进阶:线程池、文件系统、日期时间 🔜 计划中 4 Net 库:Socket / TCPServer / HTTPClient 🔜 计划中 5 Net 进阶:SSL / 异步 IO / Reactor 模式 🔜 计划中 6 Crypto / JWT / TLS 1.3 实战 🔜 计划中 7 Util 库:配置 / 日志 / 进程守护 🔜 计划中 8 Craton 自研:基于 POCO 的 RPC 框架骨架 🔜 计划中 9 Craton 自研:服务注册与发现 🔜 计划中 10 Craton 自研:分布式追踪与监控 🔜 计划中 11 Craton 自研:性能压测与对标 🔜 计划中 12 系列总结:POCO 选型决策树 🔜 计划中
前言:70% 的时间在和”基础类”打交道 我做了一份 30 天的工作时间统计:写 C++ 业务代码时,70% 的时间都在和”基础类”打交道 ——智能指针、字符串、异常、容器。
时间占比 内容 痛点 35% 字符串处理 std::string 不支持 UTF-8 感知的 trim / split / format20% 智能指针 C++11 前的项目只能用裸指针或自定义 RefCounted 15% 异常 std::exception 不知道是哪一行抛的,查 bug 像考古30% 业务代码 真正应该花时间的地方
痛点 :标准库在”工业级业务系统”面前是”够用但不好用” 。std::string 没有 format,std::exception 不带行列号,C++11 前的项目连 shared_ptr 都没有。
POCO 的 Foundation 模块给出了一套”工业级 STL 补完计划” ——它不是替代 STL ,而是补齐 STL 缺失的”业务系统常用工具” 。
读完这一篇,你将能:
能力 章节 区分 AutoPtr / SharedPtr / IntrusivePtr 的真实使用场景 第二节 用 Any / Optional / Nullable 写出”类型安全”的数据结构 第三节 掌握 Format / NumberFormatter / RegularExpression 的高频用法 第四节 设计自定义异常体系(30+ 内置异常的取舍之道) 第五节 在 QNX / 嵌入式场景用 Bugcheck + ErrorHandler 替代异常 第六节 避开 POCO Foundation 的 7 大常见坑 第八节
一、Foundation 模块全景 1.1 18 个子模块一览 POCO Foundation 不是一个”类”,而是18 个相对独立的子模块 :
# 子模块 核心类 用途 1 Core Poco::Any, Poco::Optional, Poco::Buffer<T>类型擦除、值类型、RAII 缓冲 2 Memory AutoPtr, SharedPtr, IntrusivePtr, WeakPtr智能指针家族 3 String String, StringTokenizer文本处理 4 Format Format, NumberFormatter, NumberParser格式化与解析 5 RegularExpression RegularExpression正则表达式 6 Exception Exception + 30+ 具体异常异常体系 7 Bugcheck / ErrorHandler Bugcheck, ErrorHandler断言与全局错误兜底 8 DateTime DateTime, LocalDateTime, Timezone时间处理 9 Timer Timer, Stopwatch定时器 10 Thread Thread, ThreadPool, Mutex多线程 11 Filesystem File, Directory, Path文件系统 12 Path Path路径处理 13 Process Process进程管理 14 Environment Environment环境变量 15 Logging Logger, Channel日志 16 UUID UUID唯一标识 17 URI URIURL 解析 18 Dynamic Var, VarHolder动态类型系统
graph TB
subgraph "Foundation"
CORE["🔵 Core<br/>Any/Optional/Buffer"]:::core
MEM["🟣 Memory<br/>AutoPtr/SharedPtr"]:::mem
STR["🟢 String<br/>String/Tokenizer"]:::str
FMT["🟡 Format<br/>Format/NumberFormatter"]:::fmt
REG["🟠 Regex<br/>RegularExpression"]:::reg
EXC["🔴 Exception<br/>30+ 异常类"]:::exc
BC["🩷 Bugcheck<br/>断言+错误处理"]:::bc
DT["🩵 DateTime<br/>时间"]:::dt
TH["🩶 Thread<br/>线程池"]:::th
FS["🟤 Filesystem<br/>File/Directory"]:::fs
end
CORE --> MEM
MEM --> STR
STR --> FMT
FMT --> REG
REG --> EXC
EXC --> BC
BC --> DT
DT --> TH
TH --> FS
classDef core fill:#C7CEEA,stroke:#9FA8DA,color:#333
classDef mem fill:#E8D5F5,stroke:#CE93D8,color:#333
classDef str fill:#B5EAD7,stroke:#80CBC4,color:#333
classDef fmt fill:#FFF9C4,stroke:#F9A825,color:#333
classDef reg fill:#FFDAB9,stroke:#FFAB76,color:#333
classDef exc fill:#FFB3C6,stroke:#F48FB1,color:#333
classDef bc fill:#F5F5F5,stroke:#9E9E9E,color:#333
classDef dt fill:#C7CEEA,stroke:#9FA8DA,color:#333
classDef th fill:#E8D5F5,stroke:#CE93D8,color:#333
classDef fs fill:#FFDAB9,stroke:#FFAB76,color:#333本篇范围 :第 1-7 个子模块(类型 + 字符串 + 异常 )。其余 11 个在第 3-7 篇展开。
1.2 Foundation vs 标准库:6 个核心差异 维度 标准库(C++11/14/17) POCO Foundation 业务价值 智能指针 unique_ptr / shared_ptr+ AutoPtr / IntrusivePtr / WeakPtr 兼容老代码 + 性能优化 类型擦除 std::any(C++17)Poco::Any(POCO 1.4+)比 C++17 早 5 年 就有了可选值 std::optional(C++17)Poco::Optional(POCO 1.10+)同样早 5 年 字符串 format std::format(C++20)Poco::Format(POCO 1.4+)早 15 年 !异常位置 std::exception::what()Exception 带 sourceFile / sourceLine调试效率提升 10 倍 UTF-8 字符串 std::u8string(C++20)Poco::UTFString跨平台 UTF-8 友好
核心观察 :POCO 不是”造新轮子”,而是**”补齐标准库”**。C++17 之后,很多 POCO 类都有了标准库对应,但 POCO 早 5-15 年 就提供了。
1.3 本文用到的 POCO 版本 POCO 版本 发布时间 关键类 C++ 标准 1.4 2010 Any / Format / ExceptionC++03 1.7 2015 AutoPtr 优化C++11 1.10 2019 Optional 首次引入C++11 1.13 2023 性能优化、bug 修复 C++17 1.15+ 2025 当前推荐 C++17/20
本系列基于 POCO 1.15+ ,所有示例代码均可直接编译。
二、智能指针家族 2.1 为什么需要”另一种”智能指针? C++11 已经有 std::unique_ptr / std::shared_ptr 了,为什么 POCO 还要造 4 种?
场景 std 智能指针 POCO 智能指针 原因 C++03 兼容 ❌ 无 ✅ AutoPtr 老项目无法升级 C++11 侵入式计数 ❌ 无 ✅ IntrusivePtr 性能比 shared_ptr 高 30% shared_ptr 转 weak_ptr ✅ std::weak_ptr ✅ Poco::WeakPtr POCO 内部对象图需要 STL 容器友好 ✅ unique_ptr ⚠️ AutoPtr 不友好 详见第八节
graph LR
subgraph "POCO 智能指针家族"
AP["🔵 AutoPtr<br/>兼容 C++03"]:::ap
SP["🟣 SharedPtr<br/>类型擦除 shared"]:::sp
IP["🟢 IntrusivePtr<br/>侵入式高性能"]:::ip
WP["🟡 WeakPtr<br/>观察者"]:::wp
end
subgraph "C++11 标准库"
UP["🔷 std::unique_ptr"]:::std
SSP["🔷 std::shared_ptr"]:::std
SWP["🔷 std::weak_ptr"]:::std
end
AP -.替代.-> UP
SP -.早期替代.-> SSP
WP -.对应.-> SWP
IP -.性能更优.-> SSP
style AP fill:#C7CEEA,stroke:#9FA8DA,color:#333
style SP fill:#E8D5F5,stroke:#CE93D8,color:#333
style IP fill:#B5EAD7,stroke:#80CBC4,color:#333
style WP fill:#FFF9C4,stroke:#F9A825,color:#333
style std fill:#F5F5F5,stroke:#9E9E9E,color:#3332.2 AutoPtr:POCO 1.x 的”过渡选择” AutoPtr 是 POCO 1.0 时代的主打智能指针,和 std::unique_ptr 行为类似 ,但语义不同 ——AutoPtr 支持拷贝语义 (内部用引用计数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include "Poco/AutoPtr.h" #include <iostream> class Database {public : Database (const std::string& conn) : conn_ (conn) { std::cout << "Database connect: " << conn_ << std::endl; } ~Database () { std::cout << "Database close: " << conn_ << std::endl; } void query (const std::string& sql) { std::cout << "Exec: " << sql << " via " << conn_ << std::endl; } private : std::string conn_; }; void test_autoptr () { Poco::AutoPtr<Database> db1 (new Database("mysql://localhost:3306" )) ; Poco::AutoPtr<Database> db2 = db1; Poco::AutoPtr<Database> db3 = db2; std::cout << "refcount = " << db1. referenceCount () << std::endl; db1->query ("SELECT * FROM users" ); db2->query ("SELECT * FROM orders" ); }
AutoPtr 的内部实现 (简化版):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 namespace Poco {template <class C >class AutoPtr {public : explicit AutoPtr (C* ptr = nullptr ) : _ptr(ptr), _rcPtr(nullptr) { if (_ptr) _rcPtr = new RefCount (1 ); } AutoPtr (const AutoPtr& other) : _ptr(other._ptr), _rcPtr(other._rcPtr) { if (_rcPtr) ++_rcPtr->rc; } ~AutoPtr () { release (); } AutoPtr& operator =(const AutoPtr& other) { if (this != &other) { release (); _ptr = other._ptr; _rcPtr = other._rcPtr; if (_rcPtr) ++_rcPtr->rc; } return *this ; } C* operator ->() const { return _ptr; } C& operator *() const { return *_ptr; } C* get () const { return _ptr; } int referenceCount () const { return _rcPtr ? _rcPtr->rc : 0 ; } private : void release () { if (_rcPtr && --_rcPtr->rc == 0 ) { delete _ptr; delete _rcPtr; } } struct RefCount { int rc; RefCount (int n) : rc (n) {} }; C* _ptr; RefCount* _rcPtr; }; }
核心观察 :AutoPtr 的引用计数放在外部堆 (_rcPtr),每次 new 多一次堆分配。这是它和 SharedPtr / IntrusivePtr 的关键差异。
2.3 SharedPtr:POCO 的 std::shared_ptr 替代品 SharedPtr 是 POCO 1.4 引入的智能指针,对应 std::shared_ptr :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include "Poco/SharedPtr.h" #include <iostream> #include <vector> class Connection {public : Connection (int id) : id_ (id) { std::cout << "Connect #" << id_ << std::endl; } ~Connection () { std::cout << "Disconnect #" << id_ << std::endl; } int id () const { return id_; } private : int id_; }; void test_sharedptr () { Poco::SharedPtr<Connection> p1 (new Connection(1 )) ; std::cout << "use_count = " << p1. useCount () << std::endl; { Poco::SharedPtr<Connection> p2 = p1; std::cout << "use_count = " << p1. useCount () << std::endl; std::vector<Poco::SharedPtr<Connection>> pool; pool.push_back (p1); pool.push_back (p2); std::cout << "use_count = " << p1. useCount () << std::endl; } std::cout << "use_count = " << p1. useCount () << std::endl; }
SharedPtr 关键特性 :
特性 Poco::SharedPtrstd::shared_ptr引用计数位置 外部堆(控制块) 外部堆(控制块) 自定义删除器 ✅ SharedPtr(p, deleter) ✅ shared_ptr(p, deleter) 类型擦除 ✅ 模板擦除 ✅ 模板擦除 线程安全 引用计数原子,操作不 原子 引用计数原子,操作不 原子 STL 容器支持 ✅ ✅ C++11 前可用 ✅(POCO 自实现) ❌
2.4 IntrusivePtr:性能之王 IntrusivePtr 是 POCO 智能指针家族中性能最好的 ——因为引用计数存在对象内部 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include "Poco/IntrusivePtr.h" #include <iostream> class Player : public Poco::ReferenceCounter {public : Player (const std::string& name) : name_ (name) { std::cout << "Player born: " << name_ << std::endl; } const std::string& name () const { return name_; } private : std::string name_; }; void test_intrusiveptr () { Poco::IntrusivePtr<Player> p1 (new Player("Alice" )) ; std::cout << "refcount = " << p1->referenceCount () << std::endl; Poco::IntrusivePtr<Player> p2 = p1; std::cout << "refcount = " << p1->referenceCount () << std::endl; } void benchmark () { constexpr int N = 1'000'000 ; auto start = std::chrono::high_resolution_clock::now (); for (int i = 0 ; i < N; ++i) { std::shared_ptr<int > p1 (new int (42 )) ; std::shared_ptr<int > p2 = p1; std::shared_ptr<int > p3 = p2; } auto end = std::chrono::high_resolution_clock::now (); auto shared_time = std::chrono::duration_cast <std::chrono::microseconds>(end - start).count (); start = std::chrono::high_resolution_clock::now (); for (int i = 0 ; i < N; ++i) { } }
IntrusivePtr 的本质优势 :
graph TB
subgraph "shared_ptr 内存布局"
SP_OBJ["🟢 对象<br/>int value"]:::obj
SP_CTRL["🟡 控制块<br/>shared/weak/ptr"]:::ctrl
SP_CNT["🔴 强引用计数"]:::cnt
SP_WCNT["🟠 弱引用计数"]:::wcnt
end
subgraph "IntrusivePtr 内存布局"
IP_OBJ["🟢 对象<br/>value + rc 字段"]:::obj2
IP_CNT["🟣 引用计数<br/>(对象内部)"]:::cnt2
end
SP_OBJ -.指向.-> SP_CTRL
SP_CTRL -.包含.-> SP_CNT
SP_CTRL -.包含.-> SP_WCNT
IP_OBJ -.自带.-> IP_CNT
style SP_OBJ fill:#B5EAD7,stroke:#80CBC4,color:#333
style SP_CTRL fill:#FFF9C4,stroke:#F9A825,color:#333
style SP_CNT fill:#FFB3C6,stroke:#F48FB1,color:#333
style SP_WCNT fill:#FFDAB9,stroke:#FFAB76,color:#333
style IP_OBJ fill:#B5EAD7,stroke:#80CBC4,color:#333
style IP_CNT fill:#E8D5F5,stroke:#CE93D8,color:#333核心差异 :shared_ptr 每次创建多 2 次堆分配 (对象 + 控制块),IntrusivePtr 只多 0 次 (计数在对象内部)。
2.5 WeakPtr:打破循环引用 WeakPtr 是 SharedPtr 的”观察者”——不影响引用计数 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include "Poco/SharedPtr.h" #include "Poco/WeakPtr.h" #include <iostream> class Node ; class Node : public Poco::RefCountedObject {public : Poco::SharedPtr<Node> next; Poco::WeakPtr<Node> prev; Node (int v) : value_ (v) { std::cout << "Node(" << value_ << ") born" << std::endl; } ~Node () { std::cout << "Node(" << value_ << ") die" << std::endl; } int value () const { return value_; } private : int value_; }; void test_weakptr () { Poco::SharedPtr<Node> n1 (new Node(1 )) ; Poco::SharedPtr<Node> n2 (new Node(2 )) ; Poco::SharedPtr<Node> n3 (new Node(3 )) ; n1->next = n2; n2->prev = n1; n2->next = n3; n3->prev = n2; std::cout << "n1 refcount = " << n1->referenceCount () << std::endl; std::cout << "n2 refcount = " << n2->referenceCount () << std::endl; std::cout << "n3 refcount = " << n3->referenceCount () << std::endl; Poco::SharedPtr<Node> p = n2->prev.lock (); if (p) { std::cout << "n2.prev = " << p->value () << std::endl; } n1 = nullptr ; Poco::SharedPtr<Node> p2 = n2->prev.lock (); std::cout << "After n1 release, n2.prev valid? " << (p2 ? "yes" : "no" ) << std::endl; }
循环引用 vs 弱引用对比 :
引用方式 内存泄漏风险 性能 适用场景 强引用互指 ✅ 高(典型泄漏) 快 ❌ 不推荐 强 + 弱 ❌ 无 快 ✅ 双向链表、观察者 裸指针 ❌ 需手动 最快 ⚠️ 仅限局部
2.6 智能指针家族完整对比表 维度 std::unique_ptrstd::shared_ptrPoco::AutoPtrPoco::SharedPtrPoco::IntrusivePtr所有权 独占 共享 共享 共享 共享 引用计数位置 无 外部控制块 外部 外部控制块 对象内部 拷贝 ❌ 不可 ✅ ✅ ✅ ✅ 移动 ✅ ✅ ⚠️ ✅ ✅ 自定义删除器 ✅ 模板 ✅ 函数指针 ❌ ✅ 函数指针 ❌ STL 容器 ✅ ✅ ⚠️ 见第八节 ✅ ✅ C++11 前可用 ❌ ❌ ✅ ✅ ✅ 性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ 典型场景 资源独占 默认选择 POCO 1.x 兼容 POCO 现代代码 高性能框架
选型建议 :新代码用 std::unique_ptr + std::shared_ptr ;POCO 项目内对象用 Poco::IntrusivePtr ;C++03 老代码用 Poco::AutoPtr 。
2.7 智能指针完整实战代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 #include "Poco/AutoPtr.h" #include "Poco/SharedPtr.h" #include "Poco/IntrusivePtr.h" #include "Poco/WeakPtr.h" #include "Poco/RefCountedObject.h" #include <iostream> #include <memory> #include <vector> class Service : public Poco::RefCountedObject {public : Service (const std::string& name) : name_ (name) { std::cout << "[Service " << name_ << "] created" << std::endl; } ~Service () { std::cout << "[Service " << name_ << "] destroyed" << std::endl; } const std::string& name () const { return name_; } void run () { std::cout << "[Service " << name_ << "] running" << std::endl; } private : std::string name_; }; using ServicePtr = Poco::IntrusivePtr<Service>;class ServiceRegistry {public : void registerService (const std::string& name, ServicePtr svc) { services_[name] = svc; } ServicePtr getService (const std::string& name) { auto it = services_.find (name); if (it != services_.end ()) { return it->second; } return nullptr ; } size_t count () const { return services_.size (); } private : std::map<std::string, ServicePtr> services_; }; void demo_smart_pointers () { std::cout << "=== 1. IntrusivePtr 基础 ===" << std::endl; ServicePtr svc1 (new Service("auth" )) ; std::cout << "refcount = " << svc1->referenceCount () << std::endl; { ServicePtr svc2 = svc1; std::cout << "refcount = " << svc1->referenceCount () << std::endl; } std::cout << "refcount = " << svc1->referenceCount () << std::endl; std::cout << "\n=== 2. 注册表 + 共享 ===" << std::endl; ServiceRegistry registry; registry.registerService ("auth" , svc1); std::cout << "registry size = " << registry.count () << std::endl; { ServicePtr auth = registry.getService ("auth" ); std::cout << "auth refcount = " << auth->referenceCount () << std::endl; auth->run (); } std::cout << "After scope: refcount = " << svc1->referenceCount () << std::endl; std::cout << "\n=== 3. 与 std 智能指针混用 ===" << std::endl; std::shared_ptr<Service> std_svc (svc1. get(), [svc1](Service*) mutable { }) ; }
三、容器与值类型 3.1 容器家族全景 POCO Core 模块提供了 5 个”补完 STL”的容器 :
graph TB
A["🟣 Any<br/>类型擦除"]:::any
O["🟢 Optional<br/>可选值"]:::opt
N["🟡 Nullable<br/>可空值+字符串"]:::null
T["🟠 Tuple<br/>多元组"]:::tup
B["🔵 Buffer<T><br/>RAII 字节缓冲"]:::buf
A -.替代.-> STD_ANY["std::any (C++17)"]
O -.替代.-> STD_OPT["std::optional (C++17)"]
N -.业务.-> BOOST["boost::optional"]
T -.替代.-> STD_TUP["std::tuple"]
B -.独有.-> VEC["std::vector<char>"]
style A fill:#E8D5F5,stroke:#CE93D8,color:#333
style O fill:#B5EAD7,stroke:#80CBC4,color:#333
style N fill:#FFF9C4,stroke:#F9A825,color:#333
style T fill:#FFDAB9,stroke:#FFAB76,color:#333
style B fill:#C7CEEA,stroke:#9FA8DA,color:#333
style STD_ANY fill:#F5F5F5,stroke:#9E9E9E,color:#333
style STD_OPT fill:#F5F5F5,stroke:#9E9E9E,color:#333
style BOOST fill:#F5F5F5,stroke:#9E9E9E,color:#333
style STD_TUP fill:#F5F5F5,stroke:#9E9E9E,color:#333
style VEC fill:#F5F5F5,stroke:#9E9E9E,color:#3333.2 Any:类型擦除的”魔法盒” Poco::Any 让你能在同一个容器里装任意类型 的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include "Poco/Any.h" #include <iostream> #include <string> #include <vector> #include <map> void test_any_basic () { Poco::Any a1 = 42 ; Poco::Any a2 = std::string ("hello" ); Poco::Any a3 = 3.14 ; Poco::Any a4 = true ; std::cout << "a1 = " << Poco::AnyCast <int >(a1) << std::endl; std::cout << "a2 = " << Poco::AnyCast <std::string>(a2) << std::endl; std::cout << "a3 = " << Poco::AnyCast <double >(a3) << std::endl; std::cout << "a4 = " << Poco::AnyCast <bool >(a4) << std::endl; try { int x = Poco::AnyCast <int >(a2); } catch (const Poco::BadAnyCastException& e) { std::cout << "Cast failed: " << e.displayText () << std::endl; } } class DynamicObject {public : void set (const std::string& key, Poco::Any value) { props_[key] = value; } template <typename T> T get (const std::string& key) const { auto it = props_.find (key); if (it == props_.end ()) { throw Poco::NotFoundException ("key not found: " + key); } return Poco::AnyCast <T>(it->second); } bool has (const std::string& key) const { return props_.count (key) > 0 ; } private : std::map<std::string, Poco::Any> props_; }; void test_dynamic_object () { DynamicObject obj; obj.set ("name" , std::string ("Alice" )); obj.set ("age" , 30 ); obj.set ("salary" , 5000.0 ); obj.set ("active" , true ); std::cout << "name = " << obj.get <std::string>("name" ) << std::endl; std::cout << "age = " << obj.get <int >("age" ) << std::endl; std::cout << "salary = " << obj.get <double >("salary" ) << std::endl; std::cout << "active = " << obj.get <bool >("active" ) << std::endl; }
Any 的实现原理 (简化版):
graph LR
A["🟣 Any 变量<br/>(8/16 字节)"]:::any
H["🟡 HolderBase*<br/>(虚表指针)"]:::holder
T["🟢 T 类型的实际对象<br/>(在堆上)"]:::obj
A --> H
H -.-> T
style A fill:#E8D5F5,stroke:#CE93D8,color:#333
style H fill:#FFF9C4,stroke:#F9A825,color:#333
style T fill:#B5EAD7,stroke:#80CBC4,color:#3331 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 namespace Poco {class Any {public : Any () : _content(nullptr ) {} template <typename ValueType> Any (const ValueType& value) : _content(new Holder <ValueType>(value)) {} Any (const Any& other) : _content(other._content ? other._content->clone () : nullptr ) {} ~Any () { delete _content; } template <typename ValueType> Any& operator =(const ValueType& value) { Any tmp (value); swap (tmp); return *this ; } const std::type_info& type () const { return _content ? _content->type () : typeid (void ); } private : struct HolderBase { virtual ~HolderBase () {} virtual HolderBase* clone () const = 0 ; virtual const std::type_info& type () const = 0 ; }; template <typename ValueType> struct Holder : public HolderBase { ValueType _value; Holder (const ValueType& v) : _value(v) {} HolderBase* clone () const override { return new Holder (_value); } const std::type_info& type () const override { return typeid (ValueType); } }; HolderBase* _content; void swap (Any& other) { std::swap (_content, other._content); } template <typename ValueType> friend ValueType AnyCast (const Any&) ; }; template <typename ValueType>ValueType AnyCast (const Any& any) { if (any.type () != typeid (ValueType)) { throw BadAnyCastException ("..." ); } return static_cast <Any::Holder<ValueType>*>(any._content)->_value; } }
3.3 Optional:表达”可能没有值” Poco::Optional<T> 让你能用类型安全 的方式表达”可能没有”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include "Poco/Optional.h" #include <iostream> #include <string> #include <map> Poco::Optional<int > find_first_even (const std::vector<int >& nums) { for (int n : nums) { if (n % 2 == 0 ) return n; } return Poco::Optional <int >(); } void test_optional_basic () { std::vector<int > v1 = {1 , 3 , 5 , 8 , 9 }; auto r1 = find_first_even (v1); if (r1) { std::cout << "Found: " << *r1 << std::endl; } else { std::cout << "Not found" << std::endl; } std::vector<int > v2 = {1 , 3 , 5 }; auto r2 = find_first_even (v2); std::cout << "v2 has value: " << r2. isSpecified () << std::endl; } void test_optional_valueor () { auto r = find_first_even ({1 , 3 , 5 }); int v = r.valueOr (-1 ); std::cout << "valueOr = " << v << std::endl; } class Config {public : void set (const std::string& key, const std::string& value) { data_[key] = value; } Poco::Optional<std::string> get (const std::string& key) const { auto it = data_.find (key); if (it == data_.end ()) return {}; return it->second; } std::string getOr (const std::string& key, const std::string& def) const { auto v = get (key); return v.isSpecified () ? *v : def; } private : std::map<std::string, std::string> data_; }; void test_config () { Config cfg; cfg.set ("host" , "localhost" ); cfg.set ("port" , "8080" ); std::cout << "host = " << cfg.getOr ("host" , "0.0.0.0" ) << std::endl; std::cout << "port = " << cfg.getOr ("port" , "80" ) << std::endl; std::cout << "user = " << cfg.getOr ("user" , "admin" ) << std::endl; }
3.4 Nullable:Optional 的”业务增强版” Poco::Nullable<T> 特别适合数据库字段 ——T 可以是数值类型,也支持空字符串 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include "Poco/Nullable.h" #include <iostream> #include <vector> #include <sql.h> struct UserRow { Poco::Nullable<int > id; Poco::Nullable<std::string> name; Poco::Nullable<std::string> email; Poco::Nullable<int > age; Poco::Nullable<double > salary; }; void print_user (const UserRow& u) { std::cout << "id = " << (u.id.isNull () ? "NULL" : std::to_string (*u.id)) << std::endl; std::cout << "name = " << (u.name.isNull () ? "NULL" : *u.name) << std::endl; std::cout << "email = " << (u.email.isNull () ? "NULL" : *u.email) << std::endl; std::cout << "age = " << (u.age.isNull () ? "NULL" : std::to_string (*u.age)) << std::endl; std::cout << "salary = " << (u.salary.isNull () ? "NULL" : std::to_string (*u.salary)) << std::endl; } void test_nullable () { UserRow u1; u1. id = 1 ; u1. name = "Alice" ; u1. email = nullptr ; u1. age = nullptr ; u1. salary = 5000.0 ; print_user (u1); Poco::Nullable<int > a = 10 ; Poco::Nullable<int > b; std::cout << "a + b = " << (a + b).value () << std::endl; std::cout << "a * 2 = " << (a * 2 ).value () << std::endl; }
3.5 Tuple:异构多元组 Poco::Tuple 类似 std::tuple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include "Poco/Tuple.h" #include <iostream> #include <string> using Employee = Poco::Tuple<int , std::string, std::string, double >;void test_tuple () { Employee alice (1 , "Alice" , "Engineering" , 8000.0 ) ; Employee bob (2 , "Bob" , "Sales" , 6000.0 ) ; std::cout << "Alice: ID=" << alice.get <0 >() << ", Name=" << alice.get <1 >() << ", Dept=" << alice.get <2 >() << ", Salary=" << alice.get <3 >() << std::endl; if (alice > bob) { std::cout << "Alice > Bob" << std::endl; } } using ConfigItem = Poco::Tuple<std::string, std::string>;void test_config_kv () { std::vector<ConfigItem> config = { {"host" , "localhost" }, {"port" , "8080" }, {"user" , "admin" }, }; for (const auto & item : config) { std::cout << item.get <0 >() << "=" << item.get <1 >() << std::endl; } }
3.6 Buffer:RAII 字节缓冲 Poco::Buffer<T> 是 POCO 独有的”RAII 字节缓冲 “——类似 std::vector<char>,但支持零拷贝 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include "Poco/Buffer.h" #include <iostream> #include <cstring> #include <fstream> void test_buffer_basic () { Poco::Buffer<char > buf (1024 ) ; std::strcpy (buf.begin (), "Hello, Buffer!" ); std::cout << buf.begin () << std::endl; } void read_file (const std::string& path) { std::ifstream f (path, std::ios::binary) ; if (!f) return ; f.seekg (0 , std::ios::end); size_t size = f.tellg (); f.seekg (0 , std::ios::beg); Poco::Buffer<char > data (size) ; f.read (data.begin (), size); std::cout << "Read " << data.size () << " bytes" << std::endl; } void test_buffer_zerocopy () { Poco::Buffer<char > buf (0 ) ; const char * msg = "GET / HTTP/1.1\r\n\r\n" ; buf.appendBuffer (msg, std::strlen (msg)); std::cout << "Buffer size: " << buf.size () << std::endl; std::cout << "Content: " << buf.begin () << std::endl; } void test_buffer_vs_vector () { Poco::Buffer<char > buf (100 ) ; std::vector<char > vec (100 ) ; std::vector<char > converted (buf.begin(), buf.end()) ; }
3.7 容器家族对比表 维度 Poco::Anystd::anyPoco::Optionalstd::optionalPoco::NullablePoco::Tuplestd::tuple引入版本 POCO 1.4 C++17 POCO 1.10 C++17 POCO 1.4 POCO 1.0 C++11 类型擦除 ✅ 完整 ✅ 完整 ❌ ❌ ❌ ❌ ❌ 小对象优化 ❌ 必堆分配 ✅ SSO ✅ inline ✅ inline ✅ inline ✅ inline ✅ inline 空值表达 特殊 cast 特殊 cast isSpecified()has_value()isNull()N/A N/A 算术运算 ❌ ❌ ❌ ❌ ✅ 自动 N/A N/A 业务专用 通用 通用 通用 通用 数据库 通用 通用 替代关系 早 13 年 — 早 7 年 — 唯一选择 兼容老代码 C++11+
3.8 Any / Optional / boost::any 性能对比 操作 Poco::Anystd::anyboost::any构造(int) 1 次堆分配 0 次(SSO) 1 次堆分配 构造(string) 1 次堆分配 0-1 次(SSO) 1 次堆分配 any_cast O(1) 虚函数 O(1) 直接 cast O(1) 虚函数 拷贝 1 次堆分配 0-1 次(SSO) 1 次堆分配 类型检查 typeid 对比typeid 对比typeid 对比
关键差异 :C++17 的 std::any 支持 SSO (小对象优化),比 POCO 的 Any 快很多 。新项目建议用 std::any。
3.9 容器综合实战 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include "Poco/Any.h" #include "Poco/Optional.h" #include "Poco/Buffer.h" #include <iostream> #include <unordered_map> #include <string> #include <functional> struct Message { std::string topic; std::unordered_map<std::string, Poco::Any> headers; Poco::Buffer<char > payload; Message (const std::string& t, size_t payload_size) : topic (t), payload (payload_size) {} }; using Handler = std::function<Poco::Optional <bool >(const Message&)>;class MessageBus {public : void subscribe (const std::string& topic, Handler h) { handlers_[topic].push_back (h); } void publish (const Message& msg) { auto it = handlers_.find (msg.topic); if (it == handlers_.end ()) { std::cout << "[Bus] No handler for topic: " << msg.topic << std::endl; return ; } for (auto & h : it->second) { auto result = h (msg); if (result && !*result) { std::cout << "[Bus] Handler returned false, stop" << std::endl; break ; } } } private : std::unordered_map<std::string, std::vector<Handler>> handlers_; }; void demo_message_bus () { MessageBus bus; bus.subscribe ("order" , [](const Message& msg) -> Poco::Optional<bool > { if (msg.headers.count ("priority" )) { int p = Poco::AnyCast <int >(msg.headers.at ("priority" )); std::cout << "[Order Handler] priority = " << p << std::endl; } std::cout << "[Order Handler] payload size = " << msg.payload.size () << std::endl; return true ; }); bus.subscribe ("user" , [](const Message& msg) -> Poco::Optional<bool > { std::cout << "[User Handler] received" << std::endl; return true ; }); Message order ("order" , 256 ) ; order.headers["priority" ] = 10 ; order.headers["source" ] = std::string ("gateway" ); bus.publish (order); Message user ("user" , 64 ) ; bus.publish (user); }
四、字符串与文本处理 4.1 字符串工具全景 POCO 提供 5 个字符串工具 :
工具 类 用途 替代 基础字符串 Poco::Stringstd::string 别名 + UTF-8 友好std::string分词器 StringTokenizer分割字符串 split 手写格式化 Formatprintf 风格std::format (C++20)数字格式化 NumberFormatter数字 → 字符串 std::to_string正则 RegularExpression正则表达式 std::regex
4.2 String 与 UTF-8 Poco::String 是 std::string 的类型别名,但支持 UTF-8 工具方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include "Poco/String.h" #include "Poco/UnicodeConverter.h" #include <iostream> void test_string_basic () { Poco::String s = "Hello, 世界!" ; std::cout << "Length (bytes): " << s.length () << std::endl; std::cout << "Size (bytes): " << s.size () << std::endl; std::cout << "Contains '世界'? " << Poco::icompare (s, "Hello" ) << std::endl; Poco::String upper = Poco::toUpper (s); Poco::String lower = Poco::toLower (s); std::cout << "Upper: " << upper << std::endl; Poco::String padded = " trim me " ; Poco::String trimmed = Poco::trim (padded); std::cout << "Trimmed: '" << trimmed << "'" << std::endl; Poco::String replaced = Poco::replace (s, "Hello" , "Hi" ); std::cout << "Replaced: " << replaced << std::endl; } void test_unicode_converter () { std::string utf8 = "你好世界" ; std::u16string utf16; std::u32string utf32; Poco::UnicodeConverter::toUTF16 (utf8, utf16); Poco::UnicodeConverter::toUTF32 (utf8, utf32); std::cout << "UTF-8: " << utf8 << " (" << utf8. size () << " bytes)" << std::endl; std::cout << "UTF-16: " << utf16. size () << " code units" << std::endl; std::cout << "UTF-32: " << utf32. size () << " code units" << std::endl; std::string back; Poco::UnicodeConverter::toUTF8 (utf16, back); std::cout << "Back to UTF-8: " << back << std::endl; }
4.3 StringTokenizer:分词利器 StringTokenizer 类似 Java 的 String.split,但更强大 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include "Poco/StringTokenizer.h" #include <iostream> void test_tokenizer () { Poco::StringTokenizer tokens1 ("a,b,c,d" , "," ) ; std::cout << "Count: " << tokens1. count () << std::endl; for (const auto & t : tokens1) { std::cout << " Token: " << t << std::endl; } Poco::StringTokenizer tokens2 ("a,b;c|d" , ",;|" ) ; std::cout << "Multi-delim: " << tokens2. count () << " tokens" << std::endl; Poco::StringTokenizer::Options opts; opts |= Poco::StringTokenizer::TOK_IGNORE_EMPTY; opts |= Poco::StringTokenizer::TOK_TRIM; opts |= Poco::StringTokenizer::TOK_IGNORE_QUOTES; Poco::StringTokenizer tokens3 (" a, b , ,c " , "," , opts) ; std::cout << "With opts: " << tokens3. count () << " tokens" << std::endl; for (const auto & t : tokens3) { std::cout << " '" << t << "'" << std::endl; } std::string cookie = "session=abc123; theme=dark; lang=zh-CN" ; Poco::StringTokenizer kv (cookie, ";" , opts) ; for (const auto & pair : kv) { auto pos = pair.find ('=' ); if (pos != std::string::npos) { std::string key = pair.substr (0 , pos); std::string value = pair.substr (pos + 1 ); std::cout << " Cookie: " << key << "=" << value << std::endl; } } }
StringTokenizer 选项对比表 :
选项 作用 默认值 TOK_IGNORE_EMPTY跳过空 token("a,,b" → 2 个) ❌ 关闭 TOK_TRIM修剪每个 token 的首尾空白 ❌ 关闭 `TOK_IGNORE_QUOTES** 保留引号内容 ❌ 关闭 `TOK_KEEP_EMPTY** 保留末尾空 token ❌ 关闭
Poco::Format 类似 std::format,但用 printf 语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include "Poco/Format.h" #include <iostream> #include <string> void test_format_basic () { std::string s1 = Poco::format("Hello, %s!" , "World" ); std::cout << s1 << std::endl; std::string s2 = Poco::format("%s is %d years old" , "Alice" , 30 ); std::cout << s2 << std::endl; std::string s3 = Poco::format("Price: %.2f" , 99.5 ); std::cout << s3 << std::endl; std::string s4 = Poco::format("Hex: 0x%04X" , 255 ); std::cout << s4 << std::endl; std::string s5 = Poco::format("[%-10s] [%10s]" , "left" , "right" ); std::cout << s5 << std::endl; auto log = [](const std::string& level, const std::string& msg) { return Poco::format("[%s] [%s] %s" , Poco::DateTimeFormatter::format(Poco::LocalDateTime (), "%Y-%m-%d %H:%M:%S" ), level, msg); }; std::cout << log ("INFO" , "User logged in" ) << std::endl; }
Poco::NumberFormatter 比 std::to_string 快 2-3 倍 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include "Poco/NumberFormatter.h" #include "Poco/NumberParser.h" #include <iostream> #include <chrono> void test_number_formatter () { std::string s1 = Poco::NumberFormatter::format(42 ); std::string s2 = Poco::NumberFormatter::format(0xFF , 16 ); std::string s3 = Poco::NumberFormatter::format(0b1010 , 2 ); std::cout << "Dec: " << s1 << std::endl; std::cout << "Hex: " << s2 << std::endl; std::cout << "Bin: " << s3 << std::endl; std::string s4 = Poco::NumberFormatter::format(3.1415926535 , 4 ); std::string s5 = Poco::NumberFormatter::format(3.1415926535f , 2 ); std::cout << "Pi(4): " << s4 << std::endl; std::cout << "Pi(2): " << s5 << std::endl; constexpr int N = 1'000'000 ; int value = 12345 ; auto start = std::chrono::high_resolution_clock::now (); for (int i = 0 ; i < N; ++i) { volatile std::string s = std::to_string (value); } auto t1 = std::chrono::duration_cast <std::chrono::microseconds>( std::chrono::high_resolution_clock::now () - start).count (); start = std::chrono::high_resolution_clock::now (); for (int i = 0 ; i < N; ++i) { volatile std::string s = Poco::NumberFormatter::format(value); } auto t2 = std::chrono::duration_cast <std::chrono::microseconds>( std::chrono::high_resolution_clock::now () - start).count (); std::cout << "std::to_string: " << t1 << " us" << std::endl; std::cout << "Poco::format: " << t2 << " us" << std::endl; std::cout << "Speedup: " << (double )t1 / t2 << "x" << std::endl; } void test_number_parser () { try { int i = Poco::NumberParser::parse ("42" ); double d = Poco::NumberParser::parseFloat ("3.14" ); unsigned u = Poco::NumberParser::parseUnsigned ("100" ); std::cout << "Parsed int: " << i << std::endl; std::cout << "Parsed float: " << d << std::endl; std::cout << "Parsed unsigned: " << u << std::endl; } catch (const Poco::SyntaxException& e) { std::cerr << "Parse error: " << e.displayText () << std::endl; } }
4.6 RegularExpression:正则表达式 Poco::RegularExpression 是 POCO 自带的正则引擎,比 std::regex 快 5-10 倍 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include "Poco/RegularExpression.h" #include <iostream> #include <string> void test_regex_match () { Poco::RegularExpression email_re ("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" ) ; std::string email1 = "alice@example.com" ; std::string email2 = "not-an-email" ; std::cout << email1 << " valid? " << email_re.match (email1) << std::endl; std::cout << email2 << " valid? " << email_re.match (email2) << std::endl; Poco::RegularExpression date_re ("(\\d{4})-(\\d{2})-(\\d{2})" ) ; std::string date = "2026-06-19" ; std::vector<std::string> groups; date_re.split (date, groups); std::cout << "Date parts:" << std::endl; for (const auto & g : groups) { std::cout << " " << g << std::endl; } Poco::RegularExpression num_re ("\\d+" ) ; std::string text = "Order 123 has 5 items at 99.5 yuan" ; Poco::RegularExpression::Match match; int pos = 0 ; std::cout << "Numbers found:" << std::endl; while (num_re.match (text, pos, match) != 0 ) { std::cout << " " << text.substr (match.offset, match.length) << std::endl; pos = match.offset + match.length; } } void test_regex_subst () { Poco::RegularExpression phone_re ("(\\d{3})-(\\d{4})-(\\d{4})" ) ; std::string text = "Call 138-1234-5678 or 139-8765-4321" ; std::string masked = phone_re.subst (text, "$1-****-$3" ); std::cout << "Masked: " << masked << std::endl; }
4.7 字符串工具对比表 维度 Poco::Stringstd::stringPoco::Formatstd::formatprintfPoco::RegularExpressionstd::regex引入 POCO 1.0 C++98 POCO 1.4 C++20 C89 POCO 1.0 C++11 类型安全 ✅ ✅ ✅ ✅ ❌ ✅ ✅ 性能 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ UTF-8 友好 ✅ ⚠️ 字节 ✅ ✅ ❌ ✅ ⚠️ 业务工具 ✅ 丰富 ❌ 少 ✅ printf 风格 ✅ ⚠️ 基础 ✅ 高性能 ❌ 慢
特性 Poco::Formatstd::formatfmt::format语法 printf 风格 Python 风格 Python 风格 类型安全 ✅ ✅ ✅ 编译期检查 ❌ ✅ ✅ 性能 ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 本地化 ✅ ❌ ❌ 依赖 POCO 标准库 第三方 推荐场景 既有项目 C++20 新项目 高性能新项目
4.9 字符串综合实战 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 #include "Poco/String.h" #include "Poco/StringTokenizer.h" #include "Poco/Format.h" #include "Poco/RegularExpression.h" #include <iostream> struct HttpRequest { std::string method; std::string path; std::string version; std::map<std::string, std::string> headers; std::string body; void parse (const std::string& raw) { auto sep = raw.find ("\r\n\r\n" ); std::string header_str = (sep != std::string::npos) ? raw.substr (0 , sep) : raw; if (sep != std::string::npos) body = raw.substr (sep + 4 ); Poco::StringTokenizer::Options opts = Poco::StringTokenizer::TOK_TRIM; std::vector<std::string> lines = split_lines (header_str); if (!lines.empty ()) { Poco::StringTokenizer parts (lines[0 ], " " , opts) ; if (parts.count () == 3 ) { method = parts[0 ]; path = parts[1 ]; version = parts[2 ]; } } for (size_t i = 1 ; i < lines.size (); ++i) { auto colon = lines[i].find (':' ); if (colon != std::string::npos) { std::string key = lines[i].substr (0 , colon); std::string value = lines[i].substr (colon + 1 ); Poco::trimInPlace (key); Poco::trimInPlace (value); headers[key] = value; } } } std::string to_string () const { std::string result = Poco::format("%s %s %s\r\n" , method, path, version); for (const auto & [k, v] : headers) { result += Poco::format("%s: %s\r\n" , k, v); } result += "\r\n" ; result += body; return result; } private : static std::vector<std::string> split_lines (const std::string& s) { std::vector<std::string> lines; size_t start = 0 ; size_t end; while ((end = s.find ("\r\n" , start)) != std::string::npos) { lines.push_back (s.substr (start, end - start)); start = end + 2 ; } if (start < s.size ()) lines.push_back (s.substr (start)); return lines; } }; void demo_http_parse () { std::string raw = "GET /api/users?id=1 HTTP/1.1\r\n" "Host: example.com\r\n" "User-Agent: POCO/1.15\r\n" "Content-Type: application/json\r\n" "\r\n" "{\"id\":1}" ; HttpRequest req; req.parse (raw); std::cout << "Method: " << req.method << std::endl; std::cout << "Path: " << req.path << std::endl; std::cout << "Version: " << req.version << std::endl; std::cout << "Headers:" << std::endl; for (const auto & [k, v] : req.headers) { std::cout << " " << k << ": " << v << std::endl; } std::cout << "Body: " << req.body << std::endl; }
五、异常体系 5.1 为什么需要”另一种”异常? std::exception 有什么问题?
痛点 std::exceptionPoco::Exception行列号 ❌ 无 ✅ sourceFile / sourceLine 错误码 ⚠️ 字符串里 ✅ 单独字段 嵌套 cause ❌ ✅ nested 字段 displayText what()✅ 包含所有信息 自定义层级 ⚠️ 自由发挥 ✅ 30+ 标准异常
5.2 Exception 类层级全景 graph TB
EXC["🔴 Poco::Exception<br/>(基类)"]:::exc
LOGIC["🟣 LogicException<br/>(可预防)"]:::logic
RUNTIME["🟢 RuntimeException<br/>(不可预防)"]:::runtime
IO["🟡 IOException<br/>(IO 错误)"]:::io
APP["🟠 ApplicationException<br/>(业务)"]:::app
LOGIC --> EXC
RUNTIME --> EXC
IO --> RUNTIME
APP --> RUNTIME
LOGIC -.包含.-> L1["LogicException 子类:<br/>NullPointerException<br/>InvalidArgumentException<br/>OutOfRangeException<br/>..."]:::logic2
RUNTIME -.包含.-> R1["RuntimeException 子类:<br/>NotFoundException<br/>TimeoutException<br/>SystemException<br/>..."]:::runtime2
IO -.包含.-> I1["IOException 子类:<br/>FileNotFoundException<br/>FileAccessDeniedException<br/>ConnectionException<br/>..."]:::io2
style EXC fill:#FFB3C6,stroke:#F48FB1,color:#333
style LOGIC fill:#E8D5F5,stroke:#CE93D8,color:#333
style RUNTIME fill:#B5EAD7,stroke:#80CBC4,color:#333
style IO fill:#FFF9C4,stroke:#F9A825,color:#333
style APP fill:#FFDAB9,stroke:#FFAB76,color:#333
style L1 fill:#F5F5F5,stroke:#9E9E9E,color:#333
style R1 fill:#F5F5F5,stroke:#9E9E9E,color:#333
style I1 fill:#F5F5F5,stroke:#9E9E9E,color:#3335.3 Exception 基类实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 namespace Poco {class Exception : public std::exception {public : Exception (const std::string& msg, const std::string& sourceFile = "" , int sourceLine = 0 ) : _msg(msg), _sourceFile(sourceFile), _sourceLine(sourceLine) {} Exception (const std::string& msg, const std::string& arg, const std::string& sourceFile = "" , int sourceLine = 0 ) : _msg(msg), _arg(arg), _sourceFile(sourceFile), _sourceLine(sourceLine) {} virtual ~Exception () throw () {} const char * what () const throw () override { return _msg.c_str (); } const std::string& message () const { return _msg; } const std::string& sourceFile () const { return _sourceFile; } int sourceLine () const { return _sourceLine; } const std::string& className () const { return _className; } std::string displayText () const { std::string text = _className + ": " + _msg; if (!_sourceFile.empty ()) { text += "\n in " + _sourceFile; if (_sourceLine > 0 ) { text += ":" + std::to_string (_sourceLine); } } return text; } void setNested (const Exception& nested) { _pNested = nested.clone (); } const Exception* nested () const { return _pNested.get (); } protected : virtual Exception* clone () const { return new Exception (*this ); } private : std::string _msg; std::string _arg; std::string _sourceFile; int _sourceLine; std::string _className = "Poco::Exception" ; std::unique_ptr<Exception> _pNested; }; #define POCO_THROW(EXC) throw EXC(__FILE__, __LINE__) }
5.4 30+ 内置异常分类表 类别 异常 触发场景 业务建议 LogicException LogicException逻辑错误(编程错误) 重现即可修复 NullPointerException空指针解引用 立即修复 InvalidArgumentException参数非法 加参数验证 OutOfRangeException越界访问 加边界检查 BadCastException错误的 dynamic_cast 检查类型 IllegalStateException对象状态不允许操作 加状态检查 UnimplementedException功能未实现 占位 AssertionViolationExceptionassert 失败 立即修复 RuntimeException RuntimeException运行时错误(外部) 需运行时处理 NotFoundException找不到 检查路径 TimeoutException超时 重试或降级 SystemException系统调用失败 查 errno NoMemoryException内存不足 释放资源 DataException数据格式错误 加验证 SyntaxException语法错误 查输入 IOException IOExceptionIO 错误基类 检查文件/网络 FileException文件错误基类 — FileNotFoundException文件不存在 创建文件 FileAccessDeniedException权限不足 改权限 FileReadOnlyException只读 改权限 PathSyntaxException路径非法 改路径 DirectoryNotEmptyException目录非空 清空后操作 Application ApplicationException业务异常基类 业务自定义 BadWeakPtrException弱引用失效 检查 ExistsException已存在 检查唯一性 Net NetException网络异常基类 — ConnectionException连接失败 重试 ConnectionResetException连接被重置 重连 ConnectionRefusedException拒绝连接 检查服务 DNSExceptionDNS 失败 查域名 HostNotFoundException主机找不到 — ServiceNotFoundException服务找不到 — TimeoutException超时(同上) —
5.5 LogicException vs RuntimeException 决策表 维度 LogicExceptionRuntimeExceptionIOException可预防性 ✅ 编程时避免 ❌ 运行时环境决定 ❌ 外部资源决定 是否需 catch 通常不 catch 必须 catch 必须 catch bug 严重度 严重(代码 bug) 中等 轻微 重试价值 ❌ 重试仍失败 ✅ 可能成功 ✅ 可能成功 示例 assert(x != nullptr)new 抛 NoMemoryException读文件抛 FileNotFoundException
graph LR
A["业务调用"] --> B{"异常来源"}
B -->|"代码bug"| C["LogicException"]
B -->|"外部资源"| D{"资源类型"}
D -->|"IO"| E["IOException"]
D -->|"运行时"| F["RuntimeException"]
classDef callStyle fill:#E8D5F5,stroke:#CE93D8,color:#333
classDef logicStyle fill:#FFB3C6,stroke:#F48FB1,color:#333
classDef ioStyle fill:#FFDAB9,stroke:#FFAB76,color:#333
classDef runtimeStyle fill:#B5EAD7,stroke:#80CBC4,color:#333
classDef decisionStyle fill:#FFF9C4,stroke:#F9A825,color:#333
class A callStyle
class B,D decisionStyle
class C logicStyle
class E ioStyle
class F runtimeStyle5.6 自定义异常实战 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 #include "Poco/Exception.h" #include <iostream> class BusinessException : public Poco::Exception {public : BusinessException (const std::string& msg, int errorCode = 0 , const std::string& sourceFile = "" , int sourceLine = 0 ) : Poco::Exception (msg, sourceFile, sourceLine), _errorCode(errorCode) {} int errorCode () const { return _errorCode; } std::string displayText () const { return Poco::format("[Business #%d] %s (at %s:%d)" , _errorCode, message (), sourceFile (), sourceLine ()); } protected : int _errorCode; std::string className () const { return "BusinessException" ; } }; class OrderException : public BusinessException {public : enum Code { INVALID_QUANTITY = 1001 , INSUFFICIENT_STOCK = 1002 , PAYMENT_FAILED = 1003 , SHIPPING_UNAVAILABLE = 1004 , }; OrderException (Code code, const std::string& msg, const std::string& file = "" , int line = 0 ) : BusinessException (msg, code, file, line) {} Code code () const { return static_cast <Code>(_errorCode); } }; #define THROW_ORDER(code, msg) \ throw OrderException(code, msg, __FILE__, __LINE__) class OrderService {public : void place_order (int userId, int productId, int quantity) { if (quantity <= 0 ) { THROW_ORDER (OrderException::INVALID_QUANTITY, Poco::format("Invalid quantity %d for product %d" , quantity, productId)); } if (!check_stock (productId, quantity)) { THROW_ORDER (OrderException::INSUFFICIENT_STOCK, Poco::format("Product %d has insufficient stock" , productId)); } } private : bool check_stock (int productId, int quantity) { return false ; } }; void demo_custom_exception () { OrderService svc; try { svc.place_order (1 , 100 , 5 ); } catch (const OrderException& e) { std::cout << "Order failed: " << e.displayText () << std::endl; switch (e.code ()) { case OrderException::INVALID_QUANTITY: std::cout << "-> Fix: validate quantity" << std::endl; break ; case OrderException::INSUFFICIENT_STOCK: std::cout << "-> Fix: notify user, suggest alternative" << std::endl; break ; } } catch (const Poco::Exception& e) { std::cout << "Unexpected POCO exception: " << e.displayText () << std::endl; } catch (const std::exception& e) { std::cout << "Unknown std exception: " << e.what () << std::endl; } }
5.7 Poco::Exception vs std::exception 对比表 特性 std::exceptionPoco::Exception基类继承 直接继承 继承 std::exception 位置信息 ❌ ✅ sourceFile + sourceLine 错误码 ❌ ✅ 可扩展 嵌套异常 ❌ ✅ nested() displayText ❌ ✅ 30+ 内置 ❌ ✅ 宏定义 ❌ ✅ POCO_THROW C++ 标准 C++98 POCO 1.0+
5.8 异常性能开销对比 操作 异常抛出开销 返回错误码开销 成功路径 0 ns(C++ 异常零成本) 0 ns 失败路径 1000-10000 ns(栈展开) 5-10 ns 缓存影响 ❌ 不污染 ❌ 不污染 推荐 异常路径 正常路径
核心观察 :C++ 异常在成功路径上是”零成本”的 ——编译器完全优化掉。这和 Java/C# 的”每行 try-catch 都有开销”完全不同。
六、Bugcheck & ErrorHandler 6.1 Bugcheck:更鲁棒的 assert Poco::Bugcheck 提供比 assert 更鲁棒的断言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include "Poco/Bugcheck.h" #include <iostream> #include <stdexcept> void demo_bugcheck () { int x = -1 ; assert (x > 0 ); poco_bugcheck_msg (x > 0 , "x must be positive" ); poco_assert (x > 0 ); poco_assert_msg (x > 0 , "x must be positive" ); poco_check_ptr (&x); poco_check_ptr_msg (&x, "x pointer is null" ); } class CustomBugcheckHandler {public : static void handle (const char * file, int line, const char * expr) { std::cerr << Poco::format("BUG: %s failed at %s:%d\n" , expr, file, line); std::abort (); } }; void setup_custom_handler () { Poco::Bugcheck::setHandler (&CustomBugcheckHandler::handle); }
6.2 ErrorHandler:全局错误兜底 Poco::ErrorHandler 是全局兜底 ——捕获所有 Poco::Exception(包括未处理的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include "Poco/ErrorHandler.h" #include "Poco/Exception.h" #include <iostream> class MyErrorHandler : public Poco::ErrorHandler {public : void exception (const Poco::Exception& e) override { std::cerr << "[ErrorHandler] Unhandled POCO exception: " << e.displayText () << std::endl; } void exception (const std::exception& e) override { std::cerr << "[ErrorHandler] Unhandled std exception: " << e.what () << std::endl; } void exception () override { std::cerr << "[ErrorHandler] Unknown exception" << std::endl; } }; void setup_error_handler () { static MyErrorHandler handler; Poco::ErrorHandler::setHandler (&handler); } void trigger_unhandled () { throw Poco::RuntimeException ("This is unhandled!" ); } void demo_error_handler () { setup_error_handler (); try { trigger_unhandled (); } catch (const Poco::Exception& e) { } }
6.3 Bugcheck / ErrorHandler / std::terminate 对比表 维度 Poco::BugcheckPoco::ErrorHandlerstd::terminateassert触发 断言失败 未捕获异常 未捕获异常 断言失败 能否自定义 ✅ ✅ ❌ 仅 set_terminate ❌ Release 下生效 ✅ 可配置 ✅ ✅ ❌ 编译掉 应用 Debug 检查 全局兜底 C++ 标准 简单调试
6.4 嵌入式场景的 Bugcheck 策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include "Poco/Bugcheck.h" #include "Poco/ErrorHandler.h" class EmbeddedLog : public Poco::ErrorHandler {public : void exception (const Poco::Exception& e) override { log_to_flash ("ERROR" , e.displayText ().c_str ()); } void exception (const std::exception& e) override { log_to_flash ("ERROR" , e.what ()); } void exception () override { log_to_flash ("ERROR" , "Unknown" ); } private : void log_to_flash (const char * level, const char * msg) { std::printf ("[%s] %s\n" , level, msg); } }; #define EMBEDDED_CHECK(cond, msg) \ do { \ if (!(cond)) { \ poco_bugcheck_msg(cond, msg); \ } \ } while(0) void embedded_safety_check (int * ptr) { EMBEDDED_CHECK (ptr != nullptr , "ptr is null" ); EMBEDDED_CHECK (*ptr > 0 , "ptr value must be positive" ); }
七、嵌入式场景实战 7.1 QNX / 嵌入式:禁用异常的策略 问题 :QNX 嵌入式环境禁用异常 (RTTI + 异常会增加 30-50% 体积)。
POCO 方案 :编译时宏定义禁用异常:
1 2 target_compile_definitions(mytarget PRIVATE POCO_NO_EXCEPTIONS POCO_NO_RTTI)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include "Poco/Optional.h" #include "Poco/Nullable.h" #include "Poco/Any.h" #include <iostream> Poco::Optional<int > safe_divide (int a, int b) { if (b == 0 ) { return Poco::Optional <int >(); } return a / b; } void demo_no_exceptions () { auto r1 = safe_divide (10 , 2 ); if (r1) { std::cout << "Result: " << *r1 << std::endl; } auto r2 = safe_divide (10 , 0 ); if (!r2) { std::cout << "Division by zero, but no exception thrown" << std::endl; } } class SensorReading {public : Poco::Nullable<float > temperature; Poco::Nullable<int > status; bool is_valid () const { return !temperature.isNull () && !status.isNull () && *status == 0 ; } }; struct Event { int event_id; Poco::Any payload; Event (int id, Poco::Any p) : event_id (id), payload (p) {} }; void demo_memory_constrained () { Event e1 (1 , 42 ) ; Event e2 (2 , std::string("hi" )) ; Event e3 (3 , 3.14f ) ; auto handle = [](const Event& e) { if (e.event_id == 1 ) { std::cout << "Int: " << Poco::AnyCast <int >(e.payload) << std::endl; } else if (e.event_id == 2 ) { std::cout << "Str: " << Poco::AnyCast <std::string>(e.payload) << std::endl; } }; handle (e1); handle (e2); }
7.2 内存受限环境的 Any 替代方案 容器 内存占用 适用场景 Poco::Any24 字节 + 堆 一般场景 std::variant体积 = 最大类型 C++17 推荐 Poco::Optional1 字节标志 可能为空 手动 union 体积 = 最大类型 + tag 极致内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <variant> #include <string> #include <iostream> using EventPayload = std::variant<int , std::string, float , double >;void process_payload (const EventPayload& p) { std::visit ([](auto && arg) { std::cout << "Type: " << typeid (arg).name () << ", Value: " << arg << std::endl; }, p); } void demo_variant () { process_payload (42 ); process_payload (std::string ("hello" )); process_payload (3.14f ); }
7.3 嵌入式推荐配置 graph TB
A["🟣 嵌入式系统<br/>(QNX / VxWorks / 裸机)"]:::embed
B["🟢 配置<br/>-fno-exceptions<br/>-fno-rtti"]:::config
C["🟡 POCO 编译选项<br/>POCO_NO_EXCEPTIONS=ON<br/>POCO_NO_RTTI=ON"]:::poco
D["🟠 业务代码<br/>Optional / Nullable / variant"]:::code
E["🔴 体积减少<br/>~30-50%"]:::result
A --> B --> C --> D --> E
style A fill:#E8D5F5,stroke:#CE93D8,color:#333
style B fill:#B5EAD7,stroke:#80CBC4,color:#333
style C fill:#FFF9C4,stroke:#F9A825,color:#333
style D fill:#FFDAB9,stroke:#FFAB76,color:#333
style E fill:#FFB3C6,stroke:#F48FB1,color:#333八、与其他库对比 8.1 横向对比表 维度 POCO Boost Folly Qt std Foundation 完整性 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ 智能指针 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ 字符串 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ 异常 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐ C++03 兼容 ✅ ⚠️ 部分 ❌ ✅ ❌ C++17 友好 ✅ ✅ ✅ ✅ ✅ 嵌入式友好 ✅ 可裁剪 ⚠️ ❌ ⚠️ ✅ 学习曲线 ⭐⭐⭐⭐ ⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ License Boost Boost Apache LGPL —
8.2 性能基准对比 操作 POCO Boost std 备注 shared_ptr 创建 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ POCO 略快(无 typeid) IntrusivePtr vs shared_ptr ⭐⭐⭐⭐⭐ — — 30% 性能优势 字符串 format ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ (C++20) std::format 最快正则匹配 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ POCO 比 std::regex 快 5x 异常抛出 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ 几乎无差异 内存占用 ⭐⭐⭐ ⭐⭐ ⭐⭐ POCO 较轻
8.3 选型决策树 graph TD
A["🟣 项目类型?"]:::q1
B["🟢 嵌入式 / 实时系统"]:::emb
C["🟡 业务系统 / 中间件"]:::biz
D["🔵 跨平台 GUI"]:::gui
E["🟠 推荐方案"]:::rec
A --> B
A --> C
A --> D
B --> E1["POCO + 禁异常<br/>或 std + Optional"]:::r1
C --> E2["POCO / Boost<br/>+ 标准库"]:::r2
D --> E3["Qt + POCO<br/>(只取 Foundation)"]:::r3
style A fill:#E8D5F5,stroke:#CE93D8,color:#333
style B fill:#B5EAD7,stroke:#80CBC4,color:#333
style C fill:#B5EAD7,stroke:#80CBC4,color:#333
style D fill:#B5EAD7,stroke:#80CBC4,color:#333
style E fill:#FFB3C6,stroke:#F48FB1,color:#333
style E1 fill:#B5EAD7,stroke:#80CBC4,color:#333
style E2 fill:#B5EAD7,stroke:#80CBC4,color:#333
style E3 fill:#B5EAD7,stroke:#80CBC4,color:#333九、避坑指南:7 大常见陷阱 9.1 陷阱 1:AutoPtr 不能直接用于 STL 容器 1 2 3 4 5 6 7 std::vector<Poco::AutoPtr<Foo>> v; v.push_back (new Foo); v.push_back (v.emplace_back (new Foo)); v.push_back (Poco::AutoPtr <Foo>(new Foo));
原因 :AutoPtr 的拷贝构造会修改源对象 (设为 nullptr),违反了 STL 容器的拷贝语义要求。
9.2 陷阱 2:Optional 1.10 之前的差异 版本 Optional 实现 isSpecified() valueOr() 1.4 - 1.9 Poco::Optional (轻量)✅ ❌ 1.10+ Optional<T> (重写)✅ ✅ 1.13+ Optional<T> + 算术运算✅ ✅
建议 :使用 POCO 1.10+ ,API 完善。
9.3 陷阱 3:异常的 source file/line 占用空间 1 2 3 4 5 6 7 8 throw Poco::InvalidArgumentException ("x is null" , __FILE__, __LINE__);#define POCO_THROW_MSG(EXC, msg) \ throw EXC(msg, __FILE__, __LINE__) POCO_THROW_MSG (Poco::InvalidArgumentException, "x is null" );
1 2 3 4 5 Poco::format("Hello, {}" , name); Poco::format("Hello, %s" , name.c_str ());
9.5 陷阱 5:RegularExpression 转义 1 2 3 4 5 6 Poco::RegularExpression re ("\d+" ) ; Poco::RegularExpression re (R"(\d+)" ) ;
9.6 陷阱 6:Any 拷贝性能 1 2 3 4 5 6 7 8 9 10 11 12 Poco::Any value = 42 ; for (int i = 0 ; i < 10000 ; ++i) { Poco::Any copy = value; process (copy); } Poco::Any value = 42 ; for (int i = 0 ; i < 10000 ; ++i) { process (value); }
9.7 陷阱 7:IntrusivePtr 必须继承 ReferenceCounter 1 2 3 4 5 6 7 8 9 10 11 class Foo { int x; }; Poco::IntrusivePtr<Foo> p (new Foo) ; class Foo : public Poco::RefCountedObject { int x; }; Poco::IntrusivePtr<Foo> p (new Foo) ;
9.8 7 大陷阱速查表 # 陷阱 现象 解决 1 AutoPtr 进 STL编译错误 显式构造 2 Optional 版本差异API 缺失 升级 POCO 1.10+ 3 异常位置开销 二进制膨胀 用宏 4 Format 语法编译错误 用 printf 风格 5 正则转义 匹配失败 用原始字符串 6 Any 拷贝性能差 用 move 语义 7 IntrusivePtr 基类编译错误 继承 RefCountedObject
十、总结与建议 10.1 核心要点回顾 主题 核心结论 智能指针 新代码用 std::unique_ptr / std::shared_ptr;POCO 对象用 IntrusivePtr 提升性能 容器 Any → 用 std::any(C++17+);Optional → 业务首选;Nullable → 数据库字段字符串 Poco::Format 适合老项目;C++20 用 std::format;正则 POCO 比 std 快 5x异常 业务异常必须继承 BusinessException;位置信息用宏自动捕获 错误处理 调试用 Bugcheck;生产用 ErrorHandler 兜底 嵌入式 禁用异常 + Optional + variant 是”三件套”
10.2 给不同读者的建议 读者 建议 C++ 新手 跳过 AutoPtr/SharedPtr,学 std::unique_ptr + POCO 的 Format + Exception C++03 维护者 重点用 AutoPtr + Any + Exception 三个补完 STL C++11+ 业务开发 std:: 为主,POCO 用 IntrusivePtr(框架)+ Exception(统一错误)嵌入式开发 POCO + -fno-exceptions + Optional + variant 黄金组合 框架作者 POCO 的智能指针 + 异常 + Format 几乎是”现成的”业务框架底座
10.3 后续阅读路径 第 3 篇 :DateTime / ThreadPool / Filesystem —— Foundation 进阶第 4 篇 :Socket / TCPServer / HTTPClient —— Net 模块第 8 篇 :Craton RPC 框架骨架(POCO 的实战案例 )系列导航 # 文章 状态 1 POCO 是什么?为什么我决定用 C++ 重写整个网关 ✅ 已发布 2 本文:Foundation 核心三件套 ✅ 已发布 3 Foundation 进阶:线程池、文件系统、日期时间 🔜 计划中 4 Net 库:Socket / TCPServer / HTTPClient 🔜 计划中 5 Net 进阶:SSL / 异步 IO / Reactor 模式 🔜 计划中 6 Crypto / JWT / TLS 1.3 实战 🔜 计划中 7 Util 库:配置 / 日志 / 进程守护 🔜 计划中 8 Craton 自研:基于 POCO 的 RPC 框架骨架 🔜 计划中 9 Craton 自研:服务注册与发现 🔜 计划中 10 Craton 自研:分布式追踪与监控 🔜 计划中 11 Craton 自研:性能压测与对标 🔜 计划中 12 系列总结:POCO 选型决策树 🔜 计划中
结尾金句 :POCO Foundation 不是”替代 STL”,而是”给 STL 加上工业级的脚手架 “——智能指针的 IntrusivePtr 给你 30% 性能,Exception 给你 10 倍调试效率,Format 让你从 C 风格字符串拼接的泥潭里解脱。C++ 业务系统的”基座”问题,POCO 早就替你回答了 。