16.6 unique_ptr简介与常用操作

一:unique_ptr简介

独占式的概念(专属所有权):同一时刻只能有一个 unique_ptr 指针指向这个对象(这块内存);
当这个unique_ptr被销毁时候,它所指向的对象也被销毁
格式
unique_ptr<指向的对象类型> 只能指针变量名;

<1>常规初始化( unique_ptr 和 new 配合)

int main()
{
	unique_ptr<int> pi;  //可以指向int对象的一个空智能指针
	if (pi == nullptr)
	{
		cout << "pi目前还是空指针" << endl;
	}
	unique_ptr<int> pi2(new int(100));  //此时pi2指向一个值为100的int对象

	return 0;
}

<2>make_unique函数
C++11中没有,C++14才有的make_unique,不支持指定的删除器语法,如果不用删除器,建议优先使用,更高的性能。

int main()
{
	unique_ptr<int> p1 = make_unique<int>(100);
	auto p2 = make_unique<int>(200);
	unique_ptr<int> pi2(new int(105));  //前边不能简写为auto;
	return 0;
}

二:unique_ptr的常规操作

<1>unique_ptr不支持的操作(独占式)

int main()
{
	unique_ptr<string> ps1(new string("I Love China"));
	unique_ptr<string> ps2(ps1);  //该智能指针不支持拷贝操作(定义时初始化)
	unique_ptr<string> ps3 = ps1;  //该智能指针不支持拷贝操作 和赋值 (定义时初始化)
	unique_ptr<string> ps4;
	ps4 = ps1;  //独占式智能指针不支持赋值操作
	return 0;
}

<2>移动语义

int main()
{
	unique_ptr<string> ps1(new string("I Love China"));
	unique_ptr<string> ps2 = std::move(ps1);  // 移动完后,ps1为空,ps2指向原来的ps1所指对象
	return 0;
}

<3>release()
放弃对这个指针的控制权(切断了智能指针和所指向对象之间的联系)
返回裸指针,并将该智能指针置空。返回的这个裸指针我们可以手工 delete 来释放,也可以用来初始化另外一个智能指针,或者给另外一个智能指针赋值。

int main()
{
	unique_ptr<string> ps1(new string("I Love China"));
	unique_ptr<string> ps2(ps1.release());
	if (ps1 == nullptr)
	{
		cout << "ps1被置空" << endl;
	}
	ps2.release();  //导致内存泄漏
	string* temp = ps2.release();  //suto *temp = ps2.release();
	delete temp;  //人工(手工)delete释放
	return 0;
}

<4>reset()
reset()不带参数的情况:释放智能指针所指向的对象,并将智能指针置空。

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	ps1.reset();
	if (ps1 == nullptr)
	{
		cout << "ps1被置空" << endl;
	}
	return 0;
}

reset()带参数的情况:释放智能指针所指向的对象,并让该智能指针指向新的对象。

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	unique_ptr<string> ps2(new string("I Love China2"));
	ps1.reset(ps2.release());  // reset释放ps1指向的对象内存,让ps1指向ps2所指向的内存,同时ps2被置空
	ps1.reset(new string("I Love China3"));
	return 0;
}

<5>=nullptr
释放智能指针所指向的对象,并将智能指针置空

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	ps1 = nullptr;  // 释放ps1指向的对象,并将ps1置空
	return 0;
}

<6>指向一个数组

int main()
{
	unique_ptr<int[]> ptarray(new int[10]);  // 注意:这里的数组要跟上[]
	ptarray[0] = 12;
	ptarray[1] = 24;
	return 0;
}

这里不要忘记A[], 否则如果有自己的析构函数,则会报异常
unique_ptr<A[]> ptrarray(new A[10]); //vector, string,

<7>get()
返回智能指针中保存的裸指针,考虑到有些函数参数需要的是内置裸指针(第三方库,我们更改不了代码),所以引入该函数

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	string* ps = ps1.get();
	*ps = "This is a test!";
	delete ps;  // 不可以,否则产生不可预料的后果
	return 0;
}

<8>*解引用
获取该智能指针所指向的对象,可以直接操作

int main()
{
	unique_ptr<string> ps2(new string("I Love China"));
	*ps2 = "This is a test!";
	unique_ptr<int> pt1(new int(100));
	*pt1 = 200;
	unique_ptr<int[]> pt2(new int[10]);  // 对于定的内容是数组,是没有*解引用运算符的
	*pt2[0] = 100;  //报错!
	return 0;
}

<9>swap()
交换两个智能指针所指向的对象

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	unique_ptr<string> ps2(new string("I Love China2"));
	std::swap(ps1, ps2);
	ps1.swap(ps2);
	return 0;
}

<10>智能指针名字作为判断条件

int main()
{
	unique_ptr<string> ps1(new string("I Love China1"));
	if (ps1)  //if(ps1 != nullptr)
	{
		//若ps1指向一个对象,那么这个就成立
		cout << "ps1不为空" << endl;
	}
	else
	{
		cout << "ps1为空" << endl;
	}
	ps1.reset();
	if (ps1)
	{
		//若ps1指向一个对象,那么这个就成立
		cout << "ps1不为空" << endl;
	}
	else
	{
		cout << "ps1为空" << endl;
	}
	return 0;
}

<11>转换成shared_ptr类型
如果 unique_ptr 为右值,就可以将它赋值给 shared_ptr。
因为 shared_ptr 包含一个显式构造函数,可用于将右值 unqiue_ptr 转换成 shared_ptr。
shared_ptr将接管原来的unique_ptr。

auto myfunc()
{
	return unique_ptr<string>(new string("I Love China"));  //这是个右值 (临时对象都是右值)
}
int main()
{
	shared_ptr<string> pss1 = myfunc();  // 这里会创建控制块, unique_ptr没有控制块
	unique_ptr<string> ps2(new string("I Love China"));
	shared_ptr<string> pss2 = std::move(ps2);  //左值转右值, 执行后ps2为空,pss2就是shared_ptr

	cout << sizeof(pss1) << endl;
	cout << sizeof(ps2) << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值