Learn C++学习笔记:第M章—最常用的智能指针:std::unique_ptr & std::make_unique

1、基本使用介绍

前面已经介绍了很多智能指针了,它就是一个类。这么重要的类当然不需要我们手写,有现成的可以用,它就是:

std::unique_ptr

①、所在头文件

这是一个封装好的类,包含在头文件<memory>中。

②、初始化

初始的方式也跟正常的类使用一样:

std::unique_ptr<YourClass> res{ new YourClass() };

③、智能指针之间的复制

std::unique_ptr是实现了移动语义的功能的并且禁用复制语义,在智能指针和智能指针之间的赋值时候,应该使用移动语义,先把智能指针通过std::move变成右值。

	std::unique_ptr<Resource> res1{ new Resource{} }; // Resource created here
	std::unique_ptr<Resource> res2{}; // Start as nullptr
 
	res2 = std::move(res1);

④、重载* 、->

std :: unique_ptr具有重载的operator *operator->,可用于返回被管理的资源。Operator *返回对托管资源的引用,operator->返回指针。

template<class T>
class Auto_ptr3
{
	T* m_ptr;
 	.....省略....
	T& operator*() const { return *m_ptr; }
	T* operator->() const { return m_ptr; }
};

使用示例:

#include <iostream>
#include <memory> // for std::unique_ptr
 
class Resource
{
public:
	Resource() { std::cout << "Resource acquired\n"; }
	~Resource() { std::cout << "Resource destroyed\n"; }
	friend std::ostream& operator<<(std::ostream& out, const Resource& res)
	{
		out << "I am a resource\n";
		return out;
	}

	void test(){ 
		std::cout << "=======\n";
	}
};

int main()
{
	std::unique_ptr<Resource> res{ new Resource{} };

	if (res) // use implicit cast to bool to ensure res contains a Resource
		std::cout << *res << '\n'; // print the Resource that res is owning
	res->test();
	return 0;
}

打印:

Resource acquired
I am a resource
=======
Resource destroyed

2、std :: make_unique

智能指针的初始化除了上面所示之外,更推荐使用std :: make_unique进行智能指针的创建。
使用std :: make_unique代码更简洁,并且可以避免一些错误。

auto f1{ std::make_unique<Fraction>(3, 5) };

①直接使用auto当成类型关键字即可,std :: make_unique创建的类型就是std :: unique_ptr。
②std::make_unique<ClassName>(parameter……),中间填写类名称,后面的小括号里面跟上要初始化的类的参数。

3、std::unique_ptr传递给函数和函数返回

传递给函数,因为复制语义被禁用,所以显而易见,不能直接按值传递。
并且这里要分两种情况:
①函数里面可能会对智能指针内容进行更改:

#include <iostream>
#include <memory> // for std::unique_ptr
 
class Resource
{
public:
	Resource() { std::cout << "Resource acquired\n"; }
	~Resource() { std::cout << "Resource destroyed\n"; }
	friend std::ostream& operator<<(std::ostream& out, const Resource &res)
	{
		out << "I am a resource\n";
		return out;
	}
};
 
void takeOwnership(std::unique_ptr<Resource> res)
{
     if (res)
          std::cout << *res << '\n';
} // the Resource is destroyed here
 
int main()
{
    auto ptr{ std::make_unique<Resource>() };
 
//    takeOwnership(ptr); // This doesn't work, need to use move semantics
    takeOwnership(std::move(ptr)); // ok: use move semantics
 
    std::cout << "Ending program\n";
    return 0;
}

但是需要注意的是,这里面的智能指针的销毁是在takeOwnership(std::move(ptr));后,而不是在main()后。

②如果不需要对指针内容更改,直接传递指针即可,通过get()函数,将智能指针里面的指针传递进去,使用完指针随着函数结束而销毁,并不会影响函数外面的智能指针。

#include <memory> // for std::unique_ptr
#include <iostream>
 
class Resource{
public:
	Resource() { std::cout << "Resource acquired\n"; }
	~Resource() { std::cout << "Resource destroyed\n"; }
 
	friend std::ostream& operator<<(std::ostream& out, const Resource &res)
	{
		out << "I am a resource\n";
		return out;
	}
};
 
// The function only uses the resource, so we'll accept a pointer to the resource, not a reference to the whole std::unique_ptr<Resource>
void useResource(Resource *res){
	if (res)
		std::cout << *res << '\n';
}
 
int main(){
	auto ptr{ std::make_unique<Resource>() };
 
	useResource(ptr.get()); // note: get() used here to get a pointer to the Resource
 
	std::cout << "Ending program\n";
	return 0;
} // The Resource is destroyed here

③如果是函数返回智能指针,直接正常返回即可。

std::unique_ptr<Resource> createResource(){
     return std::make_unique<Resource>();
}
 
int main(){
    auto ptr{ createResource() };
    // do whatever
    return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值