3月4日
smart_ptr 使用例子
使用智能指针不会因为忘记delete指针而造成内存泄露。还有当第三方的lib中某些函数返回指针,这样的返回的指针被client使用的时候,lib就会失去对返回的指针的控制,这样delete的指针的任务一般就会交给调用方client,但是如果client忘记调用delete或是调用的时机不正确,都有可能导致问题,在这种情况下最好使用智能指针。
使用智能指针的典型情况:
使用智能指针可以保证异常安全
保证程序在有异常抛出时仍然无内存泄露。
智能指针更好的解决了资源的所有权共享
shared_ptr<boost/shared_ptr.hpp>:使用shared_ptr进行对象的生存期自动管理,使得分享资源所有权变得有效且安全. scoped_ptr<boost/scoped_ptr.hpp>: 用于确保能够正确地删除动态分配的对象。scoped_ptr 有着与std::auto_ptr类似的特性,而最大的区别在于它不能转让所有权而auto_ptr可以。事实上,scoped_ptr永远不能被复制或被赋值!scoped_ptr 拥有它所指向的资源的所有权,并永远不会放弃这个所有权。
weak_ptr<boost/weak_ptr.hpp>:weak_ptr 是 shared_ptr 的观察员。它不会干扰shared_ptr所共享的所有权。当一个被weak_ptr所观察的 shared_ptr 要释放它的资源时,它会把相关的 weak_ptr的指针设为空。使用此辅助指针一般是防止悬空指针。intrusive_ptr<boost/intrusive_ptr.hpp>:shared_ptr的插入是版本,一般不使用,因为需要对使用此指针的类型中增加ref计数功能。但是可以保证不增加指针的大小。
scoped_array<boost/scoped_array.hpp>: scoped_array 为数组做了scoped_ptr为单个对象的指针所做的事情:它负责释放内存。
shared_array<boost/shared_array.hpp>: shared_array 用于共享数组所有权的智能指针。一般指向std::vector的shared_ptr提供了比shared_array更多的灵活性,所以一般使用std::vector<shared_ptr>。
环境boost1_38_0
#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/any.hpp>
#include <boost/format.hpp>
void PrintIfString(const boost::any& Any)
{
const boost::shared_ptr<std::string> *s =
boost::any_cast<boost::shared_ptr<std::string> >(&Any);
if (s && *s)
{
std::cout << **s << std::endl;
}
const boost::weak_ptr<std::string>* s1 =
boost::any_cast< boost::weak_ptr<std::string> >(&Any);
if(s1)
{
const boost::shared_ptr<std::string> s = s1->lock();
if(s)
{
std::cout<<"weak: "<< *s <<std::endl;
}
}
}
int main(int argc, char* argv[])
{
std::vector<boost::any> Stuff;
boost::shared_ptr<std::string> SharedString1(new std::string(
"Share me.By the way,Boost.any is another useful Boost library"));
boost::shared_ptr<std::string> SharedString2(SharedString1);
boost::shared_ptr<int> SharedInt1(new int(42));
boost::shared_ptr<int> SharedInt2 (SharedInt1);
boost::weak_ptr<std::string> ShareString3(SharedString2);
//SharedString1.reset(); 重置智能指针为NULL
//SharedString2.reset();
Stuff.push_back(SharedString1);
Stuff.push_back(SharedString2);
Stuff.push_back(SharedInt1);
Stuff.push_back(SharedInt2);
Stuff.push_back(ShareString3);
for_each(Stuff.begin(), Stuff.end(), PrintIfString);
Stuff.clear();
return 0;
}
scoped_prt 源码中,支持 if(smartptr) 判断的实现
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const
{
return px == 0? 0: &this_type::px;
}
令人发晕的类型unspecified_bool_type,这种类型实际上是"指向类的某内部成员变量的指针",不要认为它是指针类型(c必知必会上有说明)。(可以参考<<深入c++对象模型>>来查看这样的偏移值是多少)。unspecified_bool_type可以被当作bool类型使用,它要么为0,要么为1(&this_type::px总是1,错误这个是类内部成员变量的偏移值,cout输出为1是因为转换为bool类型了,可以用printf(”%p”,xx)来打印值。注意vc做了特殊处理,第一个元素偏移值打印为0,不像深入c++对象模型说的是1. 但实际上是转换判断还是为 true 的。
注意这样使用: boost::shared_ptr<int> SharedInt1(new int(42)); 而不是先new 然后赋值智能指针。在函数参数上new可以保证异常安全。除了weak_ptr都可以按这种方法来使用。
在C++标准4.12节中, 对指针与布尔值之间的关系有大致如下的描述:
任何一个指针或成员对象指针都可以转换成布尔值,空指针转换成false, 其它值转换成true.
这样我们就可以利用成员指针来进行转换。通常成员指针不可能(至少不那种容易)被隐式转换(转换的前提毕竟是类型要匹配,或可向上转换)。