智能指针的原理基于一个常见的习语叫做 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>());
}