Linux服务器开发,stl容器,智能指针,正则表达式(C++STL中的智能指针)

─────────────────────────────────────────────────────────────────
┌————————————┐
│▉▉♥♥♥♥♥♥♥♥ 99% │ ♥❤ 鱼沈雁杳天涯路,始信人间别离苦。
└————————————┘
对你的感情正在充电中,请稍侯…
────────────────────────────────────────────────────────────────

前言:
C++标准库中有四种只能指针,即std::auto_ptr、std::unique_ptr、td::shared_ptr、std::weak_ptr。每一个都有适用的场合。智能指针的作用事帮助程序员管理动态分配的对象的生命周期,更有效的防止内存的泄露。
这四种智能指针中,std::auto_ptr是98年遗留的产物,其他三种是C++11标准推出的。std::auto_ptr已经完全被std::unique_ptr取代,所以这里也不在讨论。
有了智能指针,程序员的妈妈再也不必担心内存释放影响程序员的心情了,即便忘记了delete,系统也能够帮助程序员delete,交给智能指针大家都放心了。

一、独占式指针 std::unique_ptr

同一个时间内只有一个指针能够指向该对象,当然,该对象的拥有权也能移交出去。独占式智能指针应该是最优先考虑的,可以理解为专属所有权的概念。换句话说,同一时刻只有一个指针指向这个对象,指针在对象在,指针亡对象亡。
在这里插入图片描述

#include<iostream>
#include<string>
#include<memory>
class Test
{
public:
	Test() {}
	~Test() {}//自己有析构函数
};
auto Function_10()
{
	return std::unique_ptr<std::string>(new std::string("I love Youzi"));
}
std::unique_ptr<std::string> Function_11()
{
	return std::unique_ptr< std::string>(new std::string("I love Youzi"));
}
void Function_12(std::string * arg)
{
	delete arg;
	arg = nullptr;
}
using fp = void(*)(std::string *);
typedef decltype(Function_12)* fp1;
int main()
{
	//初步认识
	std::unique_ptr<int> p1;
	if (nullptr == p1)
		std::cout << "p_test为空指针" << std::endl;

	std::unique_ptr<int> p2(new int(10));

	std::unique_ptr<int> p3 = std::make_unique<int>(10);
	auto p4 = std::make_unique<int>(10);

	//常用操作
	//1、不允许赋值、赋值等动作,只能移动不能复制的类型。
	std::unique_ptr<std::string> pa1(new std::string("I Love Ovoice"));
	//std::unique_ptr<std::string> pa2(pa1); error
	//std::unique_ptr<std::string> pa3=pa1;  error
	std::unique_ptr<std::string> pa4; 
	//pa4 = pa1; error

	//2、移动语义写法
	std::unique_ptr<std::string> pb1(new std::string("I Love Ovoice"));
	std::unique_ptr<std::string> pb2 = std::move(pb1);

	//3、放弃控制权 release()
	//放弃控制权后,返回裸指针,智能指针置空。返回的裸指针可以手工delete,也可以初始化新的,也可以去赋值。
	std::unique_ptr<std::string> pc1(new std::string("I Love Ovoice"));
	std::unique_ptr<std::string> pc2(pc1.release());

	//4、reset()成员函数
	//reset()不带参数时,释放对象,指针置空;有参数时,释放对象,指针指向新内存。
	std::unique_ptr<std::string> pd1(new std::string("I Love Ovoice"));
	pd1.reset();
	if (nullptr == pd1)
		std::cout << "pd1 == nullptr" << std::endl;

	std::unique_ptr<std::string> pd2(new std::string("I Love Ovoice"));
	std::unique_ptr<std::string> pd3(new std::string("I Love Ovoice"));
	pd3.reset(pd2.release());
	pd3.reset(new std::string("I Love Ovoice"));

	//5、释放智能指针 =nullptr
	std::unique_ptr<std::string> pe1(new std::string("I Love Ovoice"));
	pe1 = nullptr;				//高级啊,和指针一样的。

	//6、关于数组
	std::unique_ptr<int[]> pf1(new int[10]);
	pf1[0] = 11;
	pf1[1] = 22;
	pf1[2] = 33;
	
	//有析构函数的类类型,需要自己写删除器进行释放
	auto mydel = [](Test *p) {
		delete []p;
	};
	std::unique_ptr<Test[],decltype(mydel)> pf2(new Test[10], mydel);
	
	//7、获取裸指针 get()
	std::unique_ptr<std::string> pg1(new std::string("I Love Ovoice"));
	std::string * pg2 = pg1.get();
	const char* pg3 = pg2->c_str();
	*pg2 = "Ovoice is a good school!";
	const char* pg4 = pg2->c_str();//调试发现pg3和pg4内存地址不同,由string内部决定

	//8、*解引用
	std::unique_ptr<std::string> ph1(new std::string("I Love Ovoice"));
	const char* ph2 = ph1->c_str();
	*ph1 = "Ovoice is a good school!";
	const char* ph3 = ph1->c_str();
	//数组并没有解引用,注意别丢人啦
	std::unique_ptr<int[]> ph4(new int[10]);
	//*ph4; error
 
	//9、交换指向对象 swap()
	std::unique_ptr<std::string> pi1(new std::string("I Love Ovoice"));
	std::unique_ptr<std::string> pi2(new std::string("I Love Youzi"));
	std::swap(pi1,pi2); //个人推荐这种~
	pi1.swap(pi2);

	//10、转成std::share_ptr类型
	//share_ptr有一个右值构造函数可以直接将unique_ptr放入
	std::shared_ptr < std::string> pj1 = Function_10();

	std::unique_ptr<std::string> pj2(new std::string("I Love Youzi"));
	std::shared_ptr<std::string> pj3 = std::move(pj2);//pj2为空,pj3时share_ptr引用计数为1

	//11、被复制的例外
	std::unique_ptr < std::string> pk1;
	pk1 = Function_11();
	
	//12、删除器
	std::unique_ptr<std::string,fp> pl1(new std::string("I Love Youzi"),Function_12);
	std::unique_ptr<std::string, fp1> pl2(new std::string("I Love Youzi"), Function_12);
	std::unique_ptr<std::string, decltype(Function_12)*> pl3(new std::string("I Love Youzi"), Function_12);
	
	auto mydel = [](std::string* arg)
	{
		delete arg;
		arg = nullptr;
	};
	std::unique_ptr<std::string, decltype(mydel)> pl4(new std::string("I Love Youzi"), mydel);
	
	return 0;
}

二、强引用共享式指针 std::share_ptr

多个指针指向同一个对象,最后一个指针被销毁,引用计数为0,这个对象就会被销毁。
在这里插入图片描述

#include<iostream>
#include<string>
#include<memory>
#include "CShare_ptr.h"
void Function_9(int *p)
{
	std::cout << __FUNCTION__ << "现在删除器被调用" << std::endl;
	delete p;
}
template<typename T>
void Function_10(T* p)
{
	std::cout << __FUNCTION__ << "现在删除器被调用" << std::endl;
	delete []p;
}
template<typename T>
std::shared_ptr<T> make_shared_array(size_t size)
{
	return std::shared_ptr<T>(new T[size],Function_10<T[]>());
}

auto lambda1 = [](int* p)
{
	std::cout << __FUNCTION__ << "现在删除器被调用" << std::endl;
	delete p;
};
auto lambda2 = [](int* p)
{
	std::cout << __FUNCTION__ << "现在删除器被调用" << std::endl;
	delete p;
};

int main()
{
	int i{};
	std::shared_ptr<int> p=std::make_shared<int>(10);
	//1、引用计数 use_count()
	std::cout << "****** 1、引用计数 use_count()" << std::endl;
	std::shared_ptr<int> pa1(new int (100));
	std::cout << ++i<<" pa1.use_count()=" << pa1.use_count() << std::endl;
	std::shared_ptr<int> pa2(pa1);
	std::cout << ++i<<" pa1.use_count()=" << pa1.use_count() << std::endl;
	std::shared_ptr<int> pa3=pa1;
	std::cout << ++i << " pa1.use_count()=" << pa1.use_count() << std::endl;
	std::cout << ++i << " pa3.use_count()=" << pa3.use_count() << std::endl;

	//2、是否独占 unique()
	std::cout << "****** 2、是否独占 unique()" << std::endl;
	std::shared_ptr<int> pb1(new int(100));
	if (pb1.unique())
	{
		std::cout << ++i<< " pb1 unique 返回真" << std::endl;
	}
	else
	{
		std::cout << ++i << "pb1 unique 返回假" << std::endl;
	}

	//3、指针重置 reset()
	std::cout << "****** 3、指针重置 reset()" << std::endl;
	//引用计数先减1,如果为0指向的对象就要清空。
	std::shared_ptr<int> pc1(new int(100));
	pc1.reset();
	if (nullptr == pc1)
	{
		std::cout <<++i<< " pc1被置空" << std::endl;
	}
	std::shared_ptr<int> pc2(new int(100));
	//释放原内存,指向新内存
	pc2.reset(new int(100));
	
	std::shared_ptr<int> pc3;
	//利用reset初始化空指针
	pc3.reset(new int(10));
	//4、*解引用
	std::cout << "******4、*解引用" << std::endl;
	std::shared_ptr<int> pd1(new int(100));
	char buf[1024];
	sprintf_s(buf,sizeof(buf),"%d",*pd1);
	//5、获取裸指针 get()
	std::cout << "******5、获取裸指针 get()" << std::endl;
	//如果智能指针释放了对象,裸指针也将失效!这给函数的目的是为没有用智能指针的代码提供可能
	std::shared_ptr<int> pe1(new int(100));
	int* pe2 = pe1.get();
	*pe2 = 200;
	//6、交换指针 swap()
	std::cout << "******6、交换指针 swap()" << std::endl;
	std::shared_ptr<int> pf1(new int(100));
	std::shared_ptr<int> pf2(new int(100));
	std::swap(pf1,pf2);
	pf1.swap(pf2);
	//7、赋空 =nullptr
	std::cout << "7、******赋空 =nullptr" << std::endl;
	std::shared_ptr<std::string> pg1(new std::string("I love Mark!"));
	pg1 = nullptr;

	//8、删除器和数组
	std::cout << "8、******8、删除器和数组" << std::endl;
	std::shared_ptr<int> ph1(new int(100),Function_9);
	std::shared_ptr<int> ph2(ph1);
	ph1.reset();
	ph2.reset();//现在删除器会被调用

	//std::shared_ptr<int> ph3 = make_shared_array<int>(10);error 这里有待更正
	
	std::shared_ptr<int> ph4(new int(20),lambda1);
	std::shared_ptr<int> ph5(new int(20),lambda2);
	ph5 = ph4;
}

三、弱引用共享式指针std::weak_ptr

是std::share_ptr 做辅助工作的。
在这里插入图片描述

#include "CWeak_ptr.h"
#include<iostream>
#include<string>
#include<memory>
int main()
{
	int i{};
	//1、引用计数 use_count()
	std::cout << "****** 1、引用计数 use_count()" << std::endl;
	auto pa1 = std::make_shared<int>(10);
	auto pa2(pa1);
	std::weak_ptr<int> pa3(pa1);
	std::cout << ++i << " pa3.use_count()=" << pa3.use_count() << std::endl;

	//2.过期 xpired()
	pa1.reset();
	pa2.reset();
	if (pa3.expired())
	{
		std::cout << ++i << " pa3.expired()为真" << std::endl;
	}

	//3、重置 reset()
	auto pb1 = std::make_shared<int>(10);
	std::weak_ptr<int> pb2(pb1);
	pb2.reset();//pb1为强引用,弱引用已经被重置


	//4、是否锁住 lock()
	std::cout << "****** 4、是否锁住 lock()" << std::endl;
	auto pc1 = std::make_shared<int>(20);
	std::weak_ptr<int> pc2;
	pc2 = pc1;
	if (!pc2.expired())
	{
		auto pc3 = pc2.lock();
		if (pc3 != nullptr)
		{
			std::cout << "pc3 != nullptr" << "所指对象不存在" << std::endl;
		}
	}
	else
	{
		std::cout << "pc2已经过期" << std::endl;
	}
	return 0;
}

四、总结

智能指针主要目的是不光是帮助程序员用来吹牛,主要是帮助释放内存,防止内存泄露。对于严谨的程序员内存泄露是低级错误,对于新手却是家常便饭。这里只是简单的浅谈了三种智能指针日常使用的方法,日常生活中还要注意慎用裸指针、enabl_shared_from_this、循环引用等问题,避免踩坑。笔者作为一个C++初学者,还是希望在项目中多多使用智能指针,年轻人毕竟上手能力比较强嘛!
最后,还是要感谢零声学院的Darren老师,在《Linux服务器开发:stl容器,智能指针,正则表达式(C++STL中的智能指针)》这门课中着重的介绍了智能指针,让我对C++11有了新的认识!正所谓“前人播种,后人乘凉。”希望老师们继续努力,砥砺前行。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屯门山鸡叫我小鸡

加油

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值