C++智能指针

C++智能指针

  • 1.智能指针是用对象的方式管理指针,所谓的智能体现在不需要主动释放new的内存,实质是通过析构函数自动调用的特性实现的,在使用智能指针的时候一般都是构建对象,不是new一个对象
  • 2.当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。
  • 3.智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。

1.共享型智能指针

shared_ptr是共享型智能指针,允许共享对象所有权

#include<iostream>
#include<string>
#include<memory>
#include<vector>
#include<cstdio>
using namespace std;

void testOne()
{
	shared_ptr<int> p1;    //无参构造
	if (!p1)
	{
		cout << "空的智能指针对象" << endl;
		//return;
	}
	shared_ptr<int> p2(new int(123));
	//shared_ptr<int> p2=new int(123);  错误
	shared_ptr<int> p3 = make_shared<int>(1234);
	//怎么访问数据
	//直接把智能指针当作指针即可
	cout << *p3 << endl;
	//cout<<p3[0]<<endl;   //错误,没有下标法使用方式
	//获取管理对象的原生指针
	int* pNum = p3.get();
	cout << *pNum << endl;
	cout << pNum[0] << endl;
	//获取到原生指针的时候千万不要自己释放
	
	//成员函数:use_count()
	cout << "管理对象数:" << p3.use_count() << endl;
	shared_ptr<int> p4(p3);
	cout << "管理对象数:" << p3.use_count() << endl;
}
class MM
{
public:
	MM(string name,int age):name(name),age(age){}
	MM(string name):name(name),age(0){}
	MM() :name(""), age(0){};
	void print()
	{
		cout << name << "\t" << age << endl;
	}
	~MM()
	{
		cout << "释放成功" << endl;
	}
protected:
	string name;
	int age;
};
void testTwo()
{
	shared_ptr<MM> pMM(new MM("name1", 18));
	pMM->print();
	vector<MM*> arr;
	//arr.push_back(new MM("name1", 20));     释放不了,存在内存泄露
	
	//实际应用比较多的写法
	vector<shared_ptr<MM>> arr2;
	shared_ptr<MM> p(new MM("name2", 20));
	arr2.push_back(p);

	shared_ptr<MM> pMM2 = make_shared<MM>("name3", 30);
	pMM2->print();
}
//管理一段内存
void testThree()
{
	shared_ptr<int> p(new int[4]{1,2,3,4});
	//不行,但可以用原生指针去操作
	//for (int i = 0; i < 4; i++)
	//{
	//	cout << *(p + i) << endl;
	//}
	//cout << endl;
	int* pNum = p.get();
	for (int i = 0; i < 4; i++)
	{
		cout << *(pNum + i) << " ";
	}
	cout << endl;
	
	//手动删除的情况,
	//特殊内存
	//delete []pMM;
	//c语言文件指针 fopen搞内存 free释放
	shared_ptr<MM> pMM(new MM[4], [](MM*& pMM){ delete[] pMM; });
	shared_ptr<FILE> pfile(fopen("1.txt", "w+"), [](FILE*& file) {free(file); });

}
//可以当函数参数
void printMM(shared_ptr<MM> pMM)
{
	pMM->print();
}
//可以当函数返回值
shared_ptr<int> returnPoint(int num)
{
	return shared_ptr<int>(new int[num]);
}
int main()
{
	testOne();
	testTwo();
	testThree();
	return 0;
}

2.弱引用型智能指针

weak_ptr弱引用型指针,不会累计计数,存在的意义是为了解决share_ptr导致的循环引用问题

  • 1.weak_ptr只能从shared_ptr或者已有的weak_ptr去构造,不能直接管理对象
  • 2.不能直接访问管理对象(*或者->访问)
  • 3.访问数据的方式只能通过lock函数访问share_ptr 然后再去访问数据
#include<iostream>
#include<memory>
using namespace std;
class B;
class A
{
public:
	~A()
	{
		cout << "A" << endl;
	}
	weak_ptr<B> a;
};
class B
{
public:
	~B()
	{
		cout << "B" << endl;
	}
	weak_ptr<A> b;
};
void testLoopUse()
{
	shared_ptr<A> ao(new A);
	shared_ptr<B> bo(new B);
	//形成一个循环,用弱引用型指针可以释放
	ao->a = bo;
	bo->b = ao;
}

void test_weak_ptr()	
{
	//1.weak_ptr只能从shared_ptr或者已有的weak_ptr去构造,不能直接管理对象
	//2.不能直接访问管理对象(*或者->访问)
	//3.访问数据的方式只能通过lock函数访问share_ptr 然后再去访问数据
	shared_ptr<int> p(new int(123));
	cout << "count:" << p.use_count() << endl;
	weak_ptr<int> w(p);
	cout << "count:" << w.use_count() << endl;  //不会引起计数的改变
	weak_ptr<int> w2(w);
	cout << "count:" << w2.use_count() << endl;  //不会引起计数的改变
	//访问数据
	cout << *w.lock() << endl;
	shared_ptr<int> object = w.lock();
	cout << *object << endl;

}
int main()
{
	testLoopUse();
	test_weak_ptr();
	return 0;
}

3.独享型智能指针

unique_ptr 独享型就是一个对象永远都只有一个智能对象管理,实现本质是禁止拷贝,禁止复制

一般传参的话都是传引用

想要复制,可以:

  • move函数转交所有权
  • 通过reset函数 结合release函数转交所有权
#include<iostream>
#include<memory>
using namespace std;
void testOne()
{
	unique_ptr<int> p1(new int(1234));
	cout << *p1 << endl;
	unique_ptr<int> p2;
	//p2 = p1;                 //错误的
	//unique_ptr<int> p3(p1);  //错误的
	p2 = move(p1);
	cout << *p2 << endl;
	//cout << *p1 << endl;     //错误的,p1失去了管理对象

	unique_ptr<int> p3(new int(456));
	p3.reset(p2.release());
	cout << *p3 << endl;	
}
class MM
{
public:
	MM(){}
	void print()
	{
		cout << "打印测试" << endl;
	}
	~MM() { cout << "析构完成" << endl; }
protected:

};
void testTwo()
{
	//unique_ptr 删除器写法,需要手动写入删除器的类型
	unique_ptr<MM,void(*)(MM*&)> pMM(new MM[4], [](MM*& pMM) {delete[] pMM; });
	using FUNC = void(*)(MM*&);
	unique_ptr<MM, FUNC> pMM2(new MM[4], [](MM*& pMM) {delete[] pMM; });
}
//传参一般都是传引用
void printUnique(unique_ptr<MM>& pMM)
{
	pMM->print();
}
int main()
{
	testOne();
	testTwo();
	unique_ptr<MM> pMM(new MM);
	printUnique(pMM);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值