几种智能指针的比较

1.auto_ptr(已经废弃,没有使用引用计数)

智能指针头文件:memory
原因:1.不能有两个auto_ptr对象拥有同一个内部指针的所有权,因为可能在某个时机,两者均会尝试析构这个内部指针。
2.两个auto_ptr对象发生赋值时,内部指针的被拥有的所有权会发生转移,=号右值会丧失所有权,不再指向内部指针(且置为nullptr)

原因1代码:

#include<memory>
#include<iostream>
using namespace std;
int main()
{
    int *p=new int(3);
	{
	auto_ptr<int> aptr1(p);
	auto_ptr<int> aptr2(p);//指向同一个指针
	}//出作用域崩溃(因为同时对p进行了析构) 因此不要把指针*P单独声明 
	auto_ptr<int> aptr3(new int(3));//保险写法
	cout<<"aptr"<<aptr3.get()<<":"<<*aptr3<<endl;//aptr.get()返回对象的地址 *aptr对象内容
	return 0;

}

原因2代码:

#include<memory>
#include<iostream>
using namespace std;
int main()
{
  
	auto_ptr<int> aptr1(new int(0));
	auto_ptr<int> aptr2(new int(1));
	aptr2=aptr1;//这里的aptr1指向空 aptr2指向的内部指针的值为0

	return 0;
}

在这里插入图片描述
aptr.release()//释放智能指针对内部指针的所有权 但是不影响内部指针
aptr.reset§//智能指针的所有权变为p指针 且导致之前的内部指针和内容被释放(调用析构)
出错的情况:
1.函数传参(拷贝情况)时 传入智能指针时 会调用拷贝构造函数 导致函数域外的智能指针被释放。

void test(auto_ptr<int> p)//p1调用拷贝构造函数拷贝给p 释放自己
{
}
auto_ptr<int> aptr1(new int(3));
test(p1);
cout<<*p1<<endl;//报错

2.数组无法使用auto_ptr

vector<auto_ptr<int>>arry;
auto_ptr<int> p(new int(0));
arry.push_back(p);//缺乏拷贝构造
cout<<*p<<endl;

2.unique_ptr

auto_ptr升级版 限制了auto_ptr的一些构造和重载 加入了move明确语法

unique_ptr<int> p(new int(3));//正确写法
//以下会报错(因为拷贝构造 运算符重载在该类设定中被禁止了(=delete))
unique_ptr<int> p2(p);//需要拷贝构造
unique_ptr<int> p2=p;//需要拷贝构造
unique_ptr<int> p3;
p3=p;//需要运算符重载

其reset 和release与auto_ptr效果一致,多了move用法:

void move()
{
int *p=new int(3);
unique_ptr<int> p1(p);
unique_ptr<int> p2=move(p1);
//因为unique_ptr不能将内部指针直接复制给其他unique_ptr,因此使用move函数让unique_ptr交出内部指针所有权
//而自身置空,内部指针不会被释放,效果和auto_ptr一样 但是语法更加明确:剪切操作。
}
//数组处理
ary.push_back(move(p));

但是仍然无法避免剪切后p的继续操作报错的问题。

3.shared_ptr(加入引用计数)

#include<memory>
int main()
{
	shared_ptr<int> p1(new int(0));
	shared_ptr<int> p2=p1;//拷贝构造 count++

	return 0;

}

结果
在这里插入图片描述
shared_ptr为强指针 可以看到p2和p2都有内部指针ptr所有权 两者都存在 且引用计数增加为2
出错情况:
使用P指针初试化两个shared_ptr时

int *p=new int(1);
{shared_ptr<int> p1(p);
{shared_ptr<int> p2(p);}//出作用域会析构自身和释放p指针 保险写法 shared_ptr<int> p(new int(1))
}//析构报错->重复析构 

4.weak_ptr(解决循环引用)

解决循环引用在shared_ptr析构无法释放堆空间问题

#include<memory>
class cson;
class cperson{
public:cperson(){}
	   void set(shared_ptr<cson> p)
	   {   ps1=p;}
	   ~cperson(){}
   shared_ptr<cson> ps1;

};
class cson{
public:cson(){}
     void set(shared_ptr<cperson> p)//weak_ptr修改
	   { pc1=p;}
	   ~cson(){}
    shared_ptr<cperson> pc1;//weak_ptr修改

};

//两个类同时包含另一个类的智能指针 ->循环引用

void test()
{
	cson* ps=new cson();
	cperson* pp=new cperson();
	{
	shared_ptr<cperson> shared_p(pp);
	shared_ptr<cson> shared_s(ps);
	 
	shared_p->set(shared_s);
	shared_s->set(shared_p);
	cout<<shared_s.use_count()<<endl;
	cout<<shared_p.use_count()<<endl;//查看使用次数 2
	}
	//通常引用不会出现异常
	//int *p=new int(0);
	//shared_ptr<int> p1(p);

}
int main()
{
	test();//出作用域后对象ps pp指针被释放了 但是堆上的内存未被释放 循环引用出现异常
	return 0;

}

解决办法:将其中一个循环引用的强指针shared_ptr改写为weak_ptr

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值