C++26 引入了 std::indirect 类型,为 PImpl(Pointer to Implementation)手法提供了更简洁的实现方案。PImpl 是一种将类实现细节隐藏到单独类中、通过不透明指针访问的设计模式,核心目的是减少编译依赖、加快编译速度,同时隔离接口与实现。
从原始指针到智能指针的演进
传统 PImpl 使用原始指针,需要程序员手动实现「五法则」——析构函数、拷贝构造、拷贝赋值、移动构造、移动赋值共五个特殊成员函数。以 Widget 为例,类内声明前向引用的 Impl 结构体指针 pimpl_,实际定义放在 .cpp 文件中。移动语义后,被移动对象的 pimpl_ 指针置空,后续调用任何依赖该指针的成员函数都属于未定义行为。
C++11 的 std::unique_ptr 大幅简化了资源管理,new/delete 代码可由默认析构函数和移动操作的默认实现替代。但拷贝构造仍需手动定义,调用 std::make_unique<Impl>(*other.pimpl_) 深拷贝实现对象。
std::indirect 的改进
std::indirect 是 C++26 提出的新类型,专为间接值语义设计。它类似于 std::optional 但语义相反——总是持有对象,而非可能为空。std::indirect 默认支持拷贝和移动语义,消除了 PImpl 实现中手动管理 Rule of Five 的负担。此外,它具有值语义,构造时即创建对象,析构时自动销毁,天然避免了原始指针的空指针悬垂问题。对于需要频繁重编译的大型项目,std::indirect 提供了一种既安全又低维护成本的 PImpl 替代方案。
编注:信源为技术博客,材料详解了 PImpl 从原始指针到 unique_ptr 再到 std::indirect 的演进路径,并提供 Widget 类的完整代码示例。