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;
}