关于使用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; }
|
![在这里插入图片描述](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
分析:
众所周知,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); cout << *ptr << endl; 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); } int main() { int a = 10; unique_ptr<int> ptr = fun(a); cout << *ptr << endl; return 0; }
|
分析:
tmp生存期结束,将资源释放,以右值引用返回,调用移动赋值,可惜该资源已经被释放。
总结
- 所以在使用unique_ptr时,尤其是作为返回值时,请务必不要以引用或者右值引用返回!!!