zoukankan      html  css  js  c++  java
  • 转 PIMPL

    RAII 与Pimpl 源地址http://tech.uc.cn/?p=851 

    RAII

    RAII是Bjarne Stroustrup教授用于解决资源分配而发明的技术,资源获取即初始化。

    RAII是C++的构造机制的直接使用,即利用构造函数分配资源,利用析构函数来回收资源。

    我们知道,在C/C++语言中,对动态分配的内存的处理必须十分谨慎。在没有RAII应用的情况下,如果在内存释放之前就离开指针的作用域,这时候几乎没机会去释放该内存,除非垃圾回收器对其管制,否则我们要面对的将会是内存泄漏。

    举个例子来说明下RAII在内存分配方面的使用。

    这是典型的C风格代码,没有应用RAII。
    因此值得注意的是,destroy_bytearray必须在退出作用域前被调用。
    然而在复杂的逻辑设计中,程序员往往要花大量的精力以确认所有在该作用域分配的ByteArray得到正确的释放。

    相形之下,C++运行机制保证了栈上对象一旦即将离开作用域,其析构函数将被执行,给予了释放资源的时间。注意,在堆分配的对象必须调用delete来结束其生命。

    C++11 STL中的std::unique_ptr可用于控制作用域中的动态分配的对象。
    譬如:

    函数bar()只是增加了一行,但强壮了很多,函数bar()执行完或者有异常抛出时,holder总会被析构,从而ba或被delete。

    下面是ByteArray的Ada实现:

    – 输出如下
    ./main
    Create
    Initialize
    Finalize
    Finalize

    另一种情况是对I/O资源的处理,当我们不再使用资源时,必须将资源归还给系统。
    下面例子来自 wikipedia的RAII条目

    在write_to_file函数中,RAII作用于std::ofstream和std::lock_guard,从而保证了函数write_to_file在返回时,lock和file总会调用自身的析构函数,对于lock而言,它会释放mutex,而file则会close。

    Pimpl

    Pimpl(pointer to implementation),是一种应用十分广泛的技术,它的别名也很多,如Opaque pointer, handle classes等。

    wikipedia上已经对其就Ada、C和C++举例,这里不作举例。
    个人认为,Pimpl是RAII的延展,籍由RAII对资源的控制,把具体的数据布局和实现从调用者视线内移开,从而简化了API接口,也使得ABI兼容变得有可能,Qt和KDE正是使用Pimpl来维护ABI的一致性,另外也为惰性初始化提供途径,以及隐式共享提供了基础。

    我在设计代码时也会考虑使用Pimpl,但不是必然使用,因为Pimpl也会带来副作用,主要有两方面

    • Pimpl指针导致内存空间开销增大
    • 类型间Pimpl的访问需要较多间接的指针跳转,甚至还用使用friend''来提升访问权限,如以下代码中,Teacher可以访问Student的Context。

    尽管如此,我个人还是在面向开发应用的接口中会尽量使用Pimpl来维护API和ABI的一致性,除非Pimpl会引起显著的性能下降。

  • 相关阅读:
    Dockerfile
    走进Docker
    liunx 设置定时任务
    《程序员自我修养》读书笔记
    Ubuntu换源
    liunx安装python2.7.12
    预习非数值数据的编码方式
    预习原码补码
    第三章预习
    预习非数值数据的编码方式
  • 原文地址:https://www.cnblogs.com/warpengine/p/3494950.html
Copyright © 2011-2022 走看看