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,于是该对象就销毁了。