Boost(二)——智能指针

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

猜你喜欢

转载自blog.csdn.net/u012198575/article/details/83505923