[每天一道面试题 c++] Day8 讲讲你理解的c++四大智能指针

Day-8

问题

讲讲你理解的c++四大智能指针

参考答案

参考:

  1. C++里面的四个智能指针
  2. C++中的四个智能指针 博客园
  3. Auto_ptr被废弃的原因

智能指针实际上是实现了RAII思想:资源在构造期间获得,在析构期间释放。将智能指针实现为一个类,在这个类构造时申请空间,当这个类离开作用域时,析构函数被调用从而使得申请的空间自动释放,尽可能地避免了内存泄露。

c++中有四个智能指针:auto_ptrunique_ptrshared_ptrweak_ptr,其中auto_ptr已经被c++11弃用,而后三个在c++11中支持。

auto_ptr

auto_ptr采用所有权模式,对于特定的对象,只能有一个指针可以拥有。赋值操作会将所有权转移。

auto_ptr<string> p1(new string("hello world!"));    //使用智能指针一般在构造函数中申请空间
auto_ptr<string> p2=p1;
cout<<*p2<<endl;
cout<<*p1<<endl;    //报错:此时p1已经失去了对内存的所有权
PS: auto_ptr被弃用的原因

auto_ptr在c++11中被弃用的原因是:当两个auto_ptr指针都指向同一个堆空间时,每个指针析构时都会delete这个堆空间,这会导致未定义行为。

unique_ptr

unique_ptr采用独占式拥有,保证同一时间只有一个智能指针可以指向该对象

另外,unique_ptr设计更加精妙的地方在于:unique_ptr允许对临时右值进行拷贝赋值,而不允许对其他长时间存在的值进行拷贝赋值。

unique_ptr<string> p1(new string("hello world!"));
//unique_ptr<string> p2=p1;               //报错,p1是一个长时间存在的左值,不允许拷贝赋值
unique_ptr<string> p3=std::move(p1);    //允许对临时右值进行拷贝赋值
shared_ptr

shared_ptr实现共享式拥有,多个指针可以指向相同对象。它通过引用计数来统计资源被几个指针共享,当引用指针减为0时,资源会被释放。

shared_ptr<string> p1=make_shared<string>("hello world!");
shared_ptr<string> p2=p1;
cout<<*p1<<endl;            //输出:hello world!
cout<<*p2<<endl;            //输出:hello world!
cout<<p1.use_count()<<endl; //输出:2
p1.reset();                 //释放所有权
cout<<p2.use_count()<<endl; //输出:1
weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个shared_ptr管理的对象,但该weak_ptr的构造和析构不会影响shared_ptr的引用计数。weak_ptr可以配合shared_ptr一起使用,从而解决shared_ptr相互引用时的死锁问题。

下面的代码摘自参考2中的shared_ptr循环引用小节(具体可以参考原文)。

#include<iostream>
#include<memory>
using namespace std;

class ListNode{
public:
	int m_value;
	shared_ptr<ListNode> prev;
	shared_ptr<ListNode> next;
	//构造函数
	ListNode(int value):m_value(value){
		cout << "constructor called!" <<endl;
	}
	//析构函数
	~ListNode(){
		cout << "destructor called!" <<endl;
	}
};

void test(){
	shared_ptr<ListNode> sp1 = make_shared<ListNode>(33);
	shared_ptr<ListNode> sp2 = make_shared<ListNode>(44);
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
	sp1 -> next = sp2;
	sp2 -> prev = sp1;
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
}

int main(){
	test();
	return 0;
}
//运行结果:
constructor called!
constructor called!
1
1
2
2

使用weak_ptr解决循环引用:

#include<iostream>
#include<memory>
using namespace std;

class ListNode{
public:
	int m_value;
	weak_ptr<ListNode> prev;
	weak_ptr<ListNode> next;
	//构造函数
	ListNode(int value):m_value(value){
		cout << "constructor called!" <<endl;
	}
	//析构函数
	~ListNode(){
		cout << "destructor called!" <<endl;
	}
};

void test(){
	shared_ptr<ListNode> sp1 = make_shared<ListNode>(33);
	shared_ptr<ListNode> sp2 = make_shared<ListNode>(44);
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
	sp1 -> next = sp2;
	sp2 -> prev = sp1;
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
}

int main(){
	test();
	return 0;
}
//运行结果:
constructor called!
constructor called!
1
1
1
1
destructor called!
destructor called!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值