关于使用unique_ptr作为函数返回值

(1)写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
#include<memory>
using namespace std;
unique_ptr<int> fun(int x)
{
unique_ptr<int> tmp(new int(x));
return tmp;
}
int main()
{
int a = 10;
unique_ptr<int> ptr = fun(a);
cout << *ptr << endl;
return 0;
}

在这里插入图片描述

分析:
众所周知,unique_ptr中已经将拷贝构造和赋值构造函数删除了,那为什么这个fun在返回tmp没有报错呢?
原因在于:值类型返回时,tmp将采用移动构造存储在临时对象空间中,将临时空间对象再使用移动赋值转移资源给ptr对象,所以并未报错,并且十分合理。

(2)写法

1
2
3
4
5
6
7
8
9
10
11
unique_ptr<int> fun(int x)
{
return unique_ptr<int>(new int(x));
}
int main()
{
int a = 10;
unique_ptr<int> ptr = fun(a);
cout << *ptr << endl;
return 0;
}

分析:
这种写法的效率明显会比第一种写法高,少一次unique_ptr对象的构建和析构

(3)错误写法

1
2
3
4
5
6
7
8
9
10
11
12
13
unique_ptr<int>& fun(int x)
{
unique_ptr<int> tmp(new int(x));
return tmp;
}
int main()
{
int a = 10;
unique_ptr<int> ptr = fun(a); //ptr管理的对象失效
cout << *ptr << endl; //err
return 0;
}

分析:
返回值为tmp的引用,返回局部对象引用,栈帧回退时,tmp已经调用析构函数。

(4)错误写法

1
2
3
4
5
6
7
8
9
10
11
12
unique_ptr<int>&& fun(int x)
{
unique_ptr<int> tmp(new int(x));
return std::move(tmp); //tmp生存期结束,将资源释放,以右值引用返回
}
int main()
{
int a = 10;
unique_ptr<int> ptr = fun(a);
cout << *ptr << endl;
return 0;
}

分析:
tmp生存期结束,将资源释放,以右值引用返回,调用移动赋值,可惜该资源已经被释放。

总结

  • 所以在使用unique_ptr时,尤其是作为返回值时,请务必不要以引用或者右值引用返回!!!