IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++编程技巧之Pimpl手法 -> 正文阅读

[C++知识库]C++编程技巧之Pimpl手法

一、Pimpl是什么

Pimpl全称是point to implementation,译为指向实现的指针;是一种c++程序技巧。
其具有如下基本形式:

class widget {
    // 其它部分
private:
    struct impl;        // 前置申明一种变量类型
    impl* pimpl_;       // 定义该类型的指针或引用,用这个pimpl_来隐藏类widget的一些实现细节
};

二、为什么需要Pimpl技术

我们知道,在C/C++中,声明变量是不占用内存的,只有定义变量时,编译器才会为相应的变量分配对应的内存;对于一个C++的类class来说,也是如此。当在类内部定义成员变量时,会影响整个类的内存大小等相关因素;因此,若修改了类中的相关定义实现,即使该实现是private成员这是或者private函数,那么包含这个类的所有用户代码都会被重新编译;因为这些代码依赖于当前类的实现细节。
因此,为了减小编译时的依赖,就可以运用这种Pimpl技术;从其基本的定义形式就可以看出,其大小固定为一个指针大小,而指针所指对象的变化并不影响使用该指针的类的大小,这样一来,用这个impl指针来包裹类widget中容易变动的实现细节,在更改impl对象时,并不影响外部用户代码的编译;其可以带来两个好处:

  • 第一,打破编译依赖,可以使整个系统代码编译速度更快;
  • 第二,其隐藏了内部实现细节的同时,也提高了代码修改的灵活度。

三、怎么使用Pimpl技术

为了使用Pimpl技术,其基本的使用形式如下:

// in header file,即相应的.h头文件
class widget {
public:
    widget();
    ~widget();
private:
    class impl;
    unique_ptr<impl> pimpl;
};
 
// in implementation file,即相应的.cpp/.cxx等文件
class widget::impl {
    // :::
};
 
widget::widget() : pimpl{ new impl{ /*...*/ } } { }
widget::~widget() { } 

其使用细节准则如下:

  • (1)使用std::unique_ptr来管理相应的pimpl指针,这是为了更好的内存管理,避免未翻放相应内存;更详细的原理,可以查阅《Effective C++》第三版的条款13项,以对象管理资源的理念;
  • (2)在.cpp文件中定义实现widget::impl类,以达到隐藏实现细节和减少编译依赖的目的;
  • (3)在.cpp文件中,要显式定义widget::widget和widget::~widget函数,避免编译器默认生成;同样的,对于拷贝构造和赋值构造,若不想被使用,应该申明为私有;若需要被使用,也要显式定义。
  • (4)将widget中所有私有的非虚成员放入impl中去定义和实现;这也是符合OOP编程思想的理念;在OOP编程中,public成员,是为了给外部代码使用;protect和virtual成员是为了给子类继承和修改;而其它私有非虚成员,则是类的实现细节,不影响对外暴露;
  • (5)若impl类中需要访问widget的public成员,则将widget对象作为impl的成员函数的参数,进行传递;一般采用widget指针或者widget引用参数;

四、优缺点总结

优点:

  • 解除了接口和实现之间的偶合,隐藏了实现细节;
  • 减少了编译依赖性,提高编译速度;
  • 更高修改实现的灵活度,而不用考虑外部用户代码。

缺点:

  • widget的public成员函数需要通过impl指针,进一步访问对象数据,添加了一层间接性;
  • 每一个widget对象,相比于最原始实现,至少多消耗一个impl指针大小的内存;
  • widget对象必须初始化impl指针成员,动态分配impl对象;因此,也增加了动态内存分配内存(及后续释放内存)的额外开销;

参数文献:
https://en.cppreference.com/w/cpp/language/pimpl PImpl说明
https://herbsutter.com/gotw/_100/ Compilation Firewalls;
《Effective C++》第三版,条款13,条款31等;

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:05:26  更:2022-03-30 18:07:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:00:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码