duang!!!为什么函数可以返回unique_ptr

C++虐我千百遍,我待C++如初恋

从智能指针说起

对高手而言,指针是上天入地的神器;对新手而言,那简直是灾难的源泉。高级语言如Java,C#都自动管理内存,你只管new,不必操心内存释放问题。Bjarne StroustrupC认为++加入垃圾回收机制将做不适合系统底层的开发,为此C++提倡使用RAII来管理资源。auto_ptr就是根据这种理念而诞生的智能指针,本意是想编写个效率接近原生指针,但具有资源所有权安全的智能指针。当发生赋值,拷贝构造时,所有权就发生转移。这就显的很鸡肋,不能放入STL容器中,因为它的拷贝构造和传统的拷贝构造不一样。

unique_ptr取代auto_ptr

C++11的右值引用和move语义解决了这个问题,于是乎unique_ptr取代auto_ptr。为什么unique_ptr可以放入容器呢?如:

vector<unique_ptr<Song>> v;

v.push_back(unique_ptr<Song>(new Song("B‘z","Juice")));

答案是unique_ptr可以move,不能copy。它没有拷贝构造,拷贝赋值,但是有move构造,move赋值。尽管可以放入容器内,但不是所有函数都是可以用的,当然了,必要的时候可以使用std::move来将左值转化为右值。

现在,有这么一个问题,unique_ptr没有copy函数,那么,函数是如何返回unique_ptr的呢?比如C++14就有个make_unique的模板函数返回了unique_ptr。我们来看看他的实现:

template<class T,     class... Types>

unique_ptr<T> make_unique(Types&&... Args)

{

return (unique_ptr<T>(new T(forward<Types>(Args)...)));

}

这个函数会调用拷贝构造吗,一开始我也很迷惑,经过一番查找之后,基本可以确认不会调用拷贝构造。

RVO和NRVO

当函数返回一个对象时,理论上会产生临时变量,那必然是会导致新对象的构造和旧对象的析构,这对效率是有影响的。C++编译针对这种情况允许进行优化,哪怕是构造函数有副作用,这叫做返回值优化(RVO),返回有名字的对象叫做具名返回值优化(NRVO),就那RVO来说吧,本来是在返回时要生成临时对象的,现在构造返回对象时直接在接受返回对象的空间中构造了。假设不进行返回值优化,那么上面返回unique_ptr会不会有问题呢?也不会。因为标准允许编译器这么做:

1.如果支持move构造,那么调用move构造。

2.如果不支持move,那就调用copy构造。

3.如果不支持copy,那就报错吧。

显然的,unique_ptr是支持move构造的,unique_ptr对象可以被函数返回。

时间: 2024-10-26 14:38:49

duang!!!为什么函数可以返回unique_ptr的相关文章

duang!!!为什么函数能够返回unique_ptr

C++虐我千百遍,我待C++如初恋 从智能指针说起 对高手而言.指针是上天入地的神器.对新手而言,那简直是灾难的源泉.高级语言如Java,C#都自己主动管理内存.你仅仅管new.不必担心内存释放问题.Bjarne StroustrupC觉得++增加垃圾回收机制将做不适合系统底层的开发,为此C++提倡使用RAII来管理资源. auto_ptr就是依据这样的理念而诞生的智能指针,本意是想编写个效率接近原生指针,但具有资源全部权安全的智能指针.当发生赋值,拷贝构造时,全部权就发生转移. 这就显的非常鸡

【前端小小白的学习之路】----&gt;用JS编写一个函数,返回数组中重复出现过的元素

用JS编写一个函数,返回数组中重复出现过的元素,见下面的代码: var arr = [1, 2, 3, 1, 2, 3, 4, 5]; var getRepeat = function (arr) { var obj = {}; for (var i = 0, len = arr.length; i < len; i++) { if (obj[arr[i]] == undefined) { obj[arr[i]] = 1; } else { obj[arr[i]]++; } } for (var

第二天,函数的返回值return

首先是前一天问题的答案 第一题: <!DOCTYPE html> <html lang="en"> <heda> <meta charset="UTF-8">  <title></title> </head> <body> </body> </html> 第二题: 结构-HTML 表现-CSS 行为-JavaScript 第三题 <!DOCT

测试函数用Return 返回值和用函数名返回值的区别

'*************************************************************************'**模 块 名:工程1 - Form1'**说    明:蓝凤凰设计商城 浴火凤凰-郭卫 | 蓝凤凰-魔灵 | 郭卫-icecept'**创 建 人:浴火凤凰-郭卫'**日    期:2015年10月19日  21:53:17'**修 改 人:浴火凤凰-郭卫'**日    期:'**描    述:QQ:493405998 | 微信\旺旺:icece

011实现一个栈,除了push和pop操作,还要实现min函数以返回栈中的最小值,时间复杂度都为O(1)(keep it up)

实现一个栈,除了push和pop操作,还要实现min函数以返回栈中的最小值. push,pop和min函数的时间复杂度都为O(1). 看到这个题目最直接的反应是用一个变量来保存当前栈的最小值,让我们来看看这样可行否? 如果栈一直push那是没有问题,入栈元素如果比当前最小值还小,那就更新当前最小值. 可是如果pop掉的栈顶元素就是最小值,那么我们如何更新最小值呢?显然不太好办. 既然只用一个变量没法解决这个问题,那我们就增加变量.如果说每个结点除了保存当前的 值, 另外再保存一个从该结点到栈底的

赋值运算符函数的返回值类型详解

在c++赋值运算符函数的学习中,对于返回值类型的问题,一直非常费解,今天彻底总结一些每种不同返回值类型的结果: 1.当返回值为空时: <span style="font-size:14px;">void hasptr::operator=(const hasptr& s)</span> 这个时候如果只有一个'='(a = b)运算那就没问题,但是如果存在'='(a = b = c)的链式操作时,编译器就会报错 我们看:a = b = c: 程序会先运行

函数的返回值

1.params 可变参数  必须出现在参数列表的最后. 2.ref 仅仅是一个地址,引用传递,可以把值传递强制改为引用传递 3.out 让函数可以输出多个值 •1.在方法中必须为out参数赋值 •2.out参数的变量在传递之前不需要赋值,即使赋值了也不能在方法中使用.(赋值没意义) 3ref •参数在传递之前必须赋值 •在方法中可以不为ref参数赋值,可以直接使用. ref应用场景内部对外部的值进行改变,out则是内部为外部变量赋值,out一般用在函数有多个返回值的场所. 函数的返回值,布布扣

一个函数只能返回一个值?笑话

函数的define:若有两个变量x和y,对于x的每一个值,y都有唯一确定的值与它对应,则y与x有函数关系.一般用表示.其中x叫做自变量,y叫做因变量. 唯一的值?对啊,C语言函数中也是只能return 一个的而已,虽然你能写多个return 到C语言的函数中,可是见到第一个return 后,后面的操作都是不执行的.读者可以试试!!那么,我们怎样从一个C语言函数中得到多个值呢?我们可以用些技术吧???对的,真的可以!!!①可以利用指针,指针里放着变量的地址,如果我们改变它的指向,不就可以改变它的值

shell获取函数的返回值

背景:定义了一个函数,比对本地和线上服务器集群数量差别,想要获取不同集群的个数.shell和其他语言的函数返回值还是差别挺大的. 定义一个函数 functionname(){ 操作内容 echo 输出内容 return 返回值 #返回值可有可不有 } 获得函数的返回值 1.函数默认是将标准输出传递出来,不是返回值. 所以如果直接调用functionname,实际上是将输出传递回来 例如: a=`functionname` 将函数functionname的标准输出传递给a 2.调用函数不需要加()