• 2.8. 介入式指针

    2.8. 介入式指针

    大体上,介入式指针的工作方式和共享指针完全一样。 boost::shared_ptr 在内部记录着引用到某个对象的共享指针的数量,可是对介入式指针来说,程序员就得自己来做记录。 对于框架对象来说这就特别有用,因为它们记录着自身被引用的次数。

    介入式指针 boost::intrusive_ptr 定义在 boost/intrusive_ptr.hpp 里。

    1. #include <boost/intrusive_ptr.hpp>
    2. #include <atlbase.h>
    3. #include <iostream>
    4.  
    5. void intrusive_ptr_add_ref(IDispatch *p)
    6. {
    7. p->AddRef();
    8. }
    9.  
    10. void intrusive_ptr_release(IDispatch *p)
    11. {
    12. p->Release();
    13. }
    14.  
    15. void check_windows_folder()
    16. {
    17. CLSID clsid;
    18. CLSIDFromProgID(CComBSTR("Scripting.FileSystemObject"), &clsid);
    19. void *p;
    20. CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, __uuidof(IDispatch), &p);
    21. boost::intrusive_ptr<IDispatch> disp(static_cast<IDispatch*>(p));
    22. CComDispatchDriver dd(disp.get());
    23. CComVariant arg("C:\\Windows");
    24. CComVariant ret(false);
    25. dd.Invoke1(CComBSTR("FolderExists"), &arg, &ret);
    26. std::cout << (ret.boolVal != 0) << std::endl;
    27. }
    28.  
    29. void main()
    30. {
    31. CoInitialize(0);
    32. check_windows_folder();
    33. CoUninitialize();
    34. }
    • 下载源代码

    上面的例子中使用了 COM(组件对象模型)提供的函数,于是乎只能在 Windows 平台上编译运行。 COM 对象是使用 boost::intrusive_ptr 的绝佳范例,因为 COM 对象需要记录当前有多少指针引用着它。 通过调用 AddRef()Release() 函数,内部的引用计数分别增 1 或者减 1。当引用计数为 0 时,COM 对象自动销毁。

    intrusiveptr_add_ref()intrusive_ptr_release() 内部调用 AddRef()Release() 这两个函数,来增加或减少相应 COM 对象的引用计数。 这个例子中用到的 COM 对象名为 'FileSystemObject',在 Windows 上它是默认可用的。通过这个对象可以访问底层的文件系统,比如检查一个给定的目录是否存在。 在上例中,我们检查 C:\Windows 目录是否存在。 具体它在内部是怎么实现的,跟 boost::intrusive_ptr 的功能无关,完全取决于 COM。 关键点在于一旦介入式指针 _disp 离开了它的作用域——check_windows_folder() 函数的末尾,函数 intrusive_ptr_release() 将会被自动调用。 这将减少 COM 对象 'FileSystemObject' 的内部引用计数到0,于是该对象就销毁了。