Boost(二)——智能指针

xiaoxiao2025-04-27  9

 

智能指针的原理基于一个常见的习语叫做 RAII (Resource Acquisition Is Initialization):资源申请即初始化。

用一个动态分配的对象的地址来初始化智能指针,在析构的时候释放内存,就确保了这一点。 因为析构函数总是会被执行的,这样所包含的内存也将总是会被释放。

与C++——智能指针所不同。

Boost库中支持了:

1、作用域指针    boost::scoped_str:一个作用域指针独占一个动态分配的对象。 

2、作用域数组    boost::scoped_array:工作方式与1一样,但适用于多个对象。

3、共享指针    boost::shared_str:不一定要独占一个对象。 它可以和其他 boost::shared_ptr 类型的智能指针共享所有权。

4、共享数组    boost::shared_array:工作方式与3一样,但适用于多个对象。

5、弱指针    boost::weak_ptr:监控共享指针,只有在配合共享指针一起使用时才有意义。

6、介入试指针    boost::intrusive_ptr:自定义共享数量,工作方式和共享指针一样。

7、指针容器    boost::ptr_vector:存储同类智能指针。

作用域指针

#include <boost/scoped_ptr.hpp> #include <iostream> using namespace std; int main() { boost::scoped_ptr<int> i(new int); boost::scoped_ptr<int> temp(new int); *temp = 3; *i = 1; cout << *i << endl; *i.get() = 2; //改变对象的值 cout << "get >> " << *i << endl; i.swap(temp); //交换智能指针所值对象 cout << "swap i >> " << *i << endl; cout << "swap temp >> "<< *temp << endl; i.reset(new int); //重新设置地址 cout << "reset >> " << *i << endl; system("pause"); }

作用域数组

#include <boost/scoped_array.hpp> #include <algorithm> #include <iostream> using namespace std; void main() { boost::scoped_array<int> i(new int[2]); *i.get() = 5; //得到i[0]的值 i[1] = 2; i.reset(new int[3]); //重新设置数组大小 system("pause"); }

共享指针

#include <boost/shared_ptr.hpp> void main() { boost::shared_ptr<int>(new int(1)); boost::shared_ptr<int>(new int(2)); boost::shared_ptr<int> i(new int(3)); boost::shared_ptr i2(i); }

共享数组

#include <boost/shared_array.hpp> #include <iostream> using namespace std; void main() { boost::shared_array<int> i1(new int[2]); boost::shared_array<int> i2(i1); i1[0] = 1; cout << i2[0] << endl; }

弱指针

boost::weak_ptr总是通过boost::shared_ptr来初始化的。

lock() 函数:如果对象存在,那么 lock() 函数返回的共享指针指向这个合法的对象。否则,返回的共享指针被设置为0,这等价于标准的null指针。

线程开辟:调用windows的API函数

#include <windows.h> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <iostream> DWORD WINAPI reset(LPVOID p) { boost::shared_ptr<int> *sh = static_cast<boost::shared_ptr<int>*>(p); sh->reset(); return 0; } DWORD WINAPI print(LPVOID p) { boost::weak_ptr<int> *w = static_cast<boost::weak_ptr<int>*>(p); boost::shared_ptr<int> sh = w->lock(); if (sh) std::cout << *sh << std::endl; return 0; } int main() { boost::shared_ptr<int> sh(new int(99)); boost::weak_ptr<int> w(sh); //监控boost::shared_ptr HANDLE threads[2]; //开辟两个线程 threads[0] = CreateThread(0, 0, reset, &sh, 0, 0); threads[1] = CreateThread(0, 0, print, &w, 0, 0); WaitForMultipleObjects(2, threads, TRUE, INFINITE); system("pause"); }

介入试指针

#include <boost\intrusive_ptr.hpp> #include <iostream> #include <atlbase.h> using namespace std; void intrusive_ptr_add_ref(IDispatch *p)//自定义增加计数函数 { p->AddRef(); } void intrusive_ptr_release(IDispatch *p)//自定义减少计数函数 { p->Release(); } void check_windows_folder() { CLSID clsid; CLSIDFromProgID(CComBSTR("Scripting.FileSystemObject"), &clsid); //根据给定的程序标识符从注册表找出对应的类标识符 查找的是文件系统 void *p; CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, __uuidof(IDispatch), &p);//用指定的类标识符创建一个Com对象 boost::intrusive_ptr<IDispatch> disp(static_cast<IDispatch*>(p));//介入试指针指向COM对象 CComDispatchDriver dd(disp.get());//获取对象带参数的属性 CComVariant arg("C:\\Windows");//查找"C:\\Windows"是否存在 CComVariant ret(false); dd.Invoke1(CComBSTR("FolderExists"), &arg, &ret);//调用带有参数的方法 std::cout << (ret.boolVal != 0) << std::endl;//判定COM控件是否使用 } void main() { CoInitialize(0); //单线程方式构建COM组件对象 check_windows_folder(); CoUninitialize(); //卸载COM对象(与CoInitialize成对使用) }

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

在 intrusive_ptr_add_ref() 和 intrusive_ptr_release() 内部调用 AddRef() 和 Release() 这两个函数,来增加或减少相应 COM 对象的引用计数。 关键点在于一旦介入式指针 disp 离开了它的作用域——check_windows_folder() 函数的末尾,函数intrusive_ptr_release() 将会被自动调用。 这将减少 COM 对象 'FileSystemObject' 的内部引用计数到0,于是该对象就销毁了。

指针容器

#include <boost/ptr_container/ptr_vector.hpp> int main() { boost::ptr_vector<int> v; v.push_back(new int(1)); v.push_back(new int(2)); }

练习

1、使用适当的智能指针优化下面的程序:

#include <iostream> #include <cstring> char *get(const char *s) { int size = std::strlen(s); char *text = new char[size + 1]; std::strncpy(text, s, size + 1); return text; } void print(char *text) { std::cout << text << std::endl; } int main(int argc, char *argv[]) { if (argc < 2) { std::cerr << argv[0] << " <data>" << std::endl; return 1; } char *text = get(argv[1]); print(text); delete[] text; }

 改成如下:

int main(int argc, char *argv[]) { boost::shared_ptr<std::string> p(new std::string(get(argv[1]))); print((char *)(*p).data()); }

2、优化下面的程序:

#include <vector> template <typename T> T *create() { return new T; } int main() { std::vector<int*> v; v.push_back(create<int>()); }

改成如下:

int main() { boost::ptr_vector<int> pv; pv.push_back(create<int>()); }

 

转载请注明原文地址: https://www.6miu.com/read-5029272.html

最新回复(0)