最近看到项目中用到很多智能指针,之前没怎么学习,正好看到一句代码大全作者说的话,“如果你还没有养成使用auto_ptr的习惯,那么就努力吧”。听到这句话我就受刺激了。下面简单介绍下智能指针。
/*************************************************************************************
注:现在C++已经基本抛弃了auto_ptr,改为推荐使用shared_ptr。
1.auto_ptr由于他的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在
标准容器中,我们希望当容器析构时,要容器中的指针元素自动删除,会显得比较繁琐。
2.boost库提供了一个新型指针shard_ptr,它解决了多指针间共享对象所有权的问题,同时
也满足容器对元素的要求,因而可以安全地放入容器中。
*************************************************************************************/
1.auto_ptr
用指针申请动态内存时,如果不释放内存就进行销毁,那就会造成内存泄露。通过在离开作用域的时候自动释放内存,auto_ptr能避免很多与常规指针相关的内存泄露问题。
int main()
{
std::string *pStr = new string("auto_ptr");
*pStr+="C++";
cout<<*pStr<<endl;
return 0;
}
#include<memory>
int main()
{
std::tr1::shared_ptr<string> pStr(new string("auto_ptr"));
*pStr+="C++";
cout<<*pStr<<endl;
return 0;
}
第二段代码中用的是shared_ptr,顺手写了,如果用auto_ptr,直接替换就行了。
2.shared_ptr
shared_ptr有个“引用计数”的概念,我的理解就是多个变量指向的同一个内存地址,就跟引用有点像,是别称。但引用计数变成0时,这个对象就被自动删除。
class CShared
{
public:
CShared(std::tr1::shared_ptr<int> p):m_pshare(p)
{
}
~CShared()
{
}
void CSharedPrint()
{
printf("shardcount=%d,*m_pshare=%d\n",m_pshare.use_count(),*m_pshare);
}
private:
std::tr1::shared_ptr<int> m_pshare;
};
void main()
{
std::tr1::shared_ptr<int> pnew(new int(1000));
CShared share1(pnew),share2(pnew);
share1.CSharedPrint();//3,1000
share2.CSharedPrint();//3,1000
*pnew = 20;
print_fun(pnew);//3,20---------4.20
share1.CSharedPrint();//3,20
}
3.将shared_ptr应用于标准容器的用法
typedef std::tr1::shared_ptr<int> IntPtr;
typedef std::vector<IntPtr> vor_IntPtr;
vor_IntPtr vip(10);
#include <boost/make_shared.hpp>
int main()
{
typedef vector<shared_ptr<int> > vs; //一个持有shared_ptr的标准容器类型
vs v(10); //声明一个拥有10个元素的容器,元素被初始化为空指针
int i = 0;
for (vs::iterator pos = v.begin(); pos != v.end(); ++pos)
{
(*pos) = make_shared<int>(++i); //使用工厂函数赋值
cout << *(*pos) << ", "; //输出值
}
cout << endl;
shared_ptr<int> p = v[9];
*p = 100;
cout << *v[9] << endl;
}
vs2008创建的c++项目中用到了std::tr1::shared_ptr,编译时报错:error C2039: “shared_ptr”: 不是“std::tr1”的成员。
原因:未安装vs2008 SP1
4.使用规则
这个是在网上看到的,归结几点在这边,不是很全。shared_ptr不是绝对安全的。
(1)..不要构造一个临时的shared_ptr作为函数的参数。如下列代码则可能导致内存泄漏:
void test()
{
foo(boost::shared_ptr<implementation>(new implementation()),g());
}
正确的用法为 :
void test()
{
boost::shared_ptr<implementation> sp (new implementation());
foo(sp,g());
}
可能的过程是先new int,然后调g( ),g( )发生异常,shared_ptr<int>没有创建,int内存泄露,这个是boost文档上特地注明的标准bad Practices。Effective C++ Third Edition 条款17 有讲到。
(2.)不要把一个原生指针给多个shared_ptr管理
int* ptr = new int;
shared_ptr<int> p1(ptr);
shared_ptr<int> p2(ptr); //logic error