总结:
1、auto_ptr 能够拷贝,能够转移所有权
2、scoped_ptr 不能赋值或拷贝,不能转移所有权
3、weak_ptr 仅能从weak_ptr、shared_ptr类型对象构造而来,不会增加引用计数
3、养成良好的习惯
(1)注意构造函数的区别
无论是使用auto_ptr还是shared_ptr,都永远不要写这样的代码:
A* pa = new A;
xxx_ptr ptr_a_1(pa);
xxx_ptr ptr_a_2(pa);
这样,程序结束会调用两次析构函数。应该写成
xxx_ptr ptr_a_1(new A);
xxx_ptr ptr_a_2(pa);
因为shared_ptr(const shared_ptr& r); 源对象是shared_ptr时,引用计数才会加1.
而template
这个构造函数获得给定指针p的所有权。参数 p 必须是指向 Y 的有效指针。构造后引用计数设为1,所以第一种写法ptr_a_1、ptr_a_2引用计数都设为了1。
(2)谨防shared_ptr相互引用造成的内存泄漏
#include
#include
#include
using namespace boost;
using namespacestd;
class Test{
public:
Test(constchar* str){
cout <<"Test():" << str << endl;
}
~Test(){cout <<"~Test()" << endl;}
};
int main(){
//scoped_ptr不能拷贝,所有权不能转移,自动回收资源
/*exmple1*/
scoped_ptr<string> sp(newstring("Hello, world!"));
cout << *sp <<endl;
cout << sp->size() <<endl;
/*exmaple2*/
scoped_ptr<int> p(newint);//equal int *p;
if(p){
*p = 100;
cout << *p <<endl;
int* p2 = p.get();
cout << *p2 <<endl;
}
p.reset();//销毁内部对象并接受新的对象的所有权
assert(p == 0);
if(!p)
{cout <<"scoped_ptr == null" << endl;}
scoped_ptr<Test> fp(newTest("this is test class"));
auto_ptr<int> ap(new int(10));
scoped_ptr<int> sp1(ap);
assert(ap.get() == 0);//ap不再拥有指针
//int* p3 = ap.release(); //放弃内部对象的所有权,p3指向的值为10
ap.reset(newint(20));//销毁内部对象并接受新的对象的所有权
cout << *ap << "," << *sp1 << endl;
auto_ptr<int> ap2;
ap2 = ap;//转移所有权
assert(ap.get() == 0);//ap不再拥有指针
//scoped_ptr
//scoped_ptr
}
运行结果:
Hello, world!
13
100
100
scoped_ptr == null
Test():this is test class
20,10
~Test()
#include
#include
#include
using namespace std;
using namespace boost;
class Test
{
public:
Test(){cout<<"Test()"<
~Test(){cout<<"~Test()"<
};
int main()
{
shared_ptr
//shared_ptr
//cout<
//return 0;
weak_ptr
while(!w.expired()){ //w.expired()为true说明已过期
cout << w.use_count() << endl;
shared_ptr
cout << w.use_count() << endl;
if(w.use_count()==2){
break;
}
}
w.reset();
cout << w.expired() << endl;
return 0;
}
运行结果
Test()
1
2
1
~Test()
循环引用:
#include
#include
#include
#include
class parent;
class children;
typedef boost::shared_ptr
typedef boost::shared_ptr
class parent
{
public:
parent(){ std::cout<<"create parent\n";}
~parent() { std::cout <<"destroying parent\n"; }
public:
children_ptr children;
};
class children
{
public:
children() {std::cout<<"create children\n";}
~children() { std::cout <<"destroying children\n"; }
public:
parent_ptr parent;
};
void test()
{
parent_ptr father(new parent());
children_ptr son(new children);
father->children = son;
son->parent = father;
}
int main()
{
std::cout<<"begin test...\n";
test();
std::cout<<"end test...\n";
return 0;
}
begin test...
create parent
create children
end test...
由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏。
修改为weak_ptr:
#include
#include
#include
#include
class parent;
class children;
typedef boost::shared_ptr
typedef boost::shared_ptr
typedef boost::weak_ptr
class parent
{
public:
parent(){ std::cout<<"create parent\n";}
~parent() { std::cout <<"destroying parent\n"; }
public:
children_ptr children;
};
class children
{
public:
children() {std::cout<<"create children\n";}
~children() { std::cout <<"destroying children\n"; }
public:
parent_wptr parent;
};
void test()
{
parent_ptr father(new parent());
children_ptr son(new children());
father->children = son;
son->parent = father;
}
int main()
{
std::cout<<"begin test...\n";
test();
std::cout<<"end test...\n";
return 0;
}
begin test...
create parent
create children
destroying parent
destroying children
end test...