C++返回值的引用与非引用

转自:

https://blog.csdn.net/qq_22660775/article/details/89854545

返回引用与返回非引用的区别:

返回引用时,函数内部不会构造一个临时变量,而是直接将返回值返回出去。而当为非引用时,会构造一个临时变量(但不一定),然后返回这个匿名的临时变量。

举例:

class B {
public:
	B(){
		cout << "B的构造函数" << endl;
	}

	B(int i){
		cout << "带int型参数的B的构造函数" << endl;
	}

	B(const B &ano){
		cout << "B的拷贝构造函数" << endl;
	}

	B& operator=(const B& rhs){
		cout << "B的赋值操作符" << endl;
		return *this;
	}

	virtual ~B(){
		cout << "B的析构函数" << endl;
	}
};
B func2()
{
	B b;
	return b;
}

int main() {

	B t;
	t=func2();
     //B z=func2();
	cout<<endl;
}

  结果为:

实际上这个过程是:

首先在main中生成t,调用一个默认构造函数

然后在func2()中生成一个b,调用一个默认构造函数

然后要返回b了,使用拷贝构造,利用b拷贝构造一个临时变量tmp

然后析构b

然后利用tmp赋值给t

最后析构这个临时变量tmp

可以看到,整个过程,由于使用的是非引用,因此会首先调用拷贝构造构造临时变量tmp,然后返回这个tmp

而当调用B z=func2()时:

首先进入func2,对b进行构造

但这里没有构造临时变量,由于外面是B z=func2(),实际上是直接将这个z传入,然后利用b来拷贝构造这个z,最后再析构b

注意这里析构的顺序,在上面看到,构造完临时变量tmp后,b直接就析构了,然后tmp赋值给t后tmp才析构。注意这里b的析构时间和上一行的析构时间:

上一行是利用b构造完z后b才析构,也就是说实际上是将这个z当做tmp来拷贝构造。

而最前面是先拷贝构造tmp,然后b马上析构,最后用tmp来给b赋值。

也就是说:

如果返回的是非引用,并不一定会构造一个临时变量。

如果使用B z=func2()这种方式是不会生成临时变量的;但B b;b=func2();是会生成临时变量的。

 

想到上次去网易面试时考官问我的一个问题:

这个返回的ans怎么提高效率?

如果用引用返回的话则会出问题,因为返回的是局部对象,在赋值的时候实际上已经析构了。

当时的回答是将结果作为参数放入func()中,也就是改写为void func(vector<int>& result);然后这样就可以提高效率

但面试官应该想让我get到另外的点

难道是移动语义或者完美转发?这个我还没看,需要好好研究下。

vector<int> func()
{
	vector<int> ans(2,1);

	return ans;
}

  

原文地址:https://www.cnblogs.com/lxy-xf/p/11558802.html

时间: 2024-12-19 06:06:28

C++返回值的引用与非引用的相关文章

C++函数返回引用、非引用以及临时变量的问题

C++中新增了引用类型,所以函数的返回值可以是引用类型.那么就会有人想问 返回引用类型与返回非引用类型有区别吗? 结论是显然的,而且有明显的区别.尤其初学者会很容易绕进去.让我们先看四个函数原型.以int类型来举例 (1) int fun(...) { return ....//后面跟的是一个引用 } 例如:int fun(int &a) { return a; } (2)int fun(...) { return....//后面跟的是一个非引用 } 例如:int  fun(int a) { r

关于C++函数思考2(函数返回引用和返回非引用的区别)

引用是提高代码效率的一大利器,尤其对于对象来说,当引用作为参数时候不用大面积的复制对象本身所造成的空间与时间的浪费.所以有时候对于参数的返回值我们也希望返回参数的引用.在这里我们回忆一下C语言函数返回局部变量所注意的方面,也可以看我的这篇文章.下来我们对于C++ 中函数返回引用或非引用进行探讨!! 1.返回引用 /********************************************************************** * * Copyright (c)2015

java只有值传递,不存在引用传递

今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这一特性很是熟悉! 结果发现,我错了! 答案是: 值传递!Java中只有按值传递,没有按引用传递! 回家后我就迫不及待地查询了这个问题,觉得自己对java这么基础的问题都搞错实在太丢人! 综合网上的描述,我大概了解了是怎么回事,现在整理如下,如有不对之处望大神提出! 先来看一个作为程序员都熟悉的值传递

C++ 赋值构造函数的返回值到底有什么用?且返回值是否为引用类型有什么区别吗?

首先定义类Person class Person{ public: string name; Person()=default; //默认构造函数 Person(string nam):name(nam){} void operator=(const Person& p){ //赋值构造函数 this->name=p.name; } }; Person a("xiaoming"); Person b; cout<<b.name<<endl; //空

C#中返回值封装

在平时开发过程中常常需要取一个方法的返回值,BOSS写了一个返回值类,做个练习以备不时之需: 返回值支持泛型和非泛型 先贴上代码: 非泛型返回值类: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Serialization; 6 7 8 namespace WindowsFormsApplication31 9

理解-加号重载要使用全局函数+返回值非引用

一.C++中的加号重载使用全局函数的一个有点是可以使用级联的方式进行加法操作. Fraction a,b,c,d,e; A=b+c+d+e; 若为成员函数 1.返回的b的this指针分别作用于后面的变量,因此是对b的修改: 2.如果返回一个新的变量,上面的级联的问题似乎可以解决. 3.问题在于如果存在隐式类型转换,且第一个参数为需要转化的类型时,可能找不到该定义的成员函数,因此使用全局的方式可以便面这个问题 二.返回值需要时一个值,而不是引用 从一个局部函数返回引用,可以考虑两种情况. 1.如果

将引用作为函数返回值的优缺点

格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }好处:在内存中不产生被返回值的副本:(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的.因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!注意事项:(1)不能返回局部变量的引用.这条可以参照Effective C++[1]的Item 31.主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态.(2)不能返回函数内部new

将引用作为函数返回值的格式、好处和规则

格式: 类型标识符 &函数名(形参列表及类型说明){//函数体} 好处: 在内存中不产生返回值的副本(返回一个局部变量的引用是不可取的,因为随着局部变量生存周期的结束,相应的引用也会失效,产生runtime error) 注意: 不能返回局部变量的引用,局部变量会在函数返回后被销毁. 不能返回函数内部new分配的内存的引用,虽然不存在局部变量的被动销毁问题,但是函数返回的引用只是作为一个临时变量出现,并没有被赋予一个实际的变量,导致引用所指向的空间无法释放. 可以返回类成员的引用,但最好是con

为什么赋值操作符函数的参数为const引用,返回值为引用

为什么赋值操作符函数的参数为const引用,返回值为引用 1.返回值类型 返回类型一般声明为类型的引用,并在函数结尾时返回实例自身的引用(即*this).这里主要有两个原因:(1)返回引用可以减少一次拷贝构造和析构函数导致不必要的开销,因为返回值类型不是引用,会创建一个匿名对象,这个匿名对象时个右值,获取return的值.(2)可以实现连续赋值 在例子中 b=c=a; 返回值不是引用类型也是可以的,其运算顺序 b=(c=a); c得到一个右值,再将右值赋给b,所以逻辑上没有问题的.但是如果是 (