c++临时对象以及引用的一些知识

一:先来讲讲什么是临时对象。
临时对象(临时变量):代码中看不见,隐藏在后台,因此我们无法在程序代码中看见临时对象。
临时对象的产生条件有两个: 1.为使函数调用成功而进行隐式类型转换时用到。 2.函数返回值的时候用到

1.为使函数调用成功时

void conv(string str){  ...  }
int main(){
  conv("abcd");
  }

//这种情况下,abcd并不是直接传给str,而是先传递给临时对象,再由临时对象传递给形参str,因为他们俩的类型不一样,(对,你没有看错,这俩类型就是不一样,一个const类型,一个非const类型,所以需要隐式类型转换),看下面的图。
在这里插入图片描述
这仅仅是一个参数,所以复制临时对象占用的内存基本可以忽略,但是我们想一想,实际编程中怎么可能只有一组数据,必定是有大量的数据来调用同一个函数的,这样每一个数据我都复制一个临时对象,那么这样占用的内存是非常大的,所以我们要避免让其产生临时对象的这种写法。结合我们之前学的引用传递&,我们发现,引用传递是不需要进行临时对象复制的,因此省下了好多内存。但是问题结束了吗?
答案是不可能的,好了,那么问题又来了,众所周知引用传递是不需要产生临时对象的,我直接就把实参传给str,这样一来就有个小问题,abcd这个字符串常量是const类型,但是str是非const类型,把一个const类型赋给一个非const类型是不允许的。
因此 下面这种使用引用的写法会报错。

#include<iostream>
#include<string>
using namespace std;
void conv(string &str){ //会报错 
	cout<<"1"<<endl;
}
int main(){
    conv("abcd"); 
}

在这里插入图片描述
那有没有什么解决办法呢?

答案是有的:就是加一个const,把非const类型的形参str变成const类型。
写法一:
#include<iostream>
#include<string>
using namespace std;
void conv(const string &str){ //这样就不会报错 ,但是str不能再被修改了。
	cout<<"1"<<endl;
}
int main(){
    conv("abcd"); 
}
写法二:重要知识点,非const类型的引用时参数只能时相同类型,而const类型可以实现传递于此类型相关的参数进来。
#include<iostream>
#include<string>
using namespace std;
void conv(string &str){ //这样就不会报错 
	cout<<"1"<<endl;
}
int main(){
    string str="abcd";
    conv(str);  这样也可以, 
}


2.函数返回值的时候会产生临时对象(不使用引用&的前提,使用引用或者指针会在下面介绍):

void get(){
.....
}

在这里插入图片描述

接下来细讲函数返回值的其他两种方式(不产生临时对象):一是指针,二是引用 。

1.先讲讲指针返回(局部变量不能被返回,but why?)
在这里插入图片描述

例1:把调用的函数直接设置为指针类型

int *get10(){
int a=10;
int *b=&a;
return b;
}
int main(){
int *c=get10();
cout<<*c<<endl;
}
//我们实际运行一下,会发现可以运行,这个时候我们会有疑问,那这样不是和我前面那个不能返回局部变量的结论冲突了吗?
//其实是因为c++的内存清理机制是惰性的,它并不会在此函数调用完立即清除其占用的内存,而是会在下一个函数进来之后才把上一个函数的内存释放掉。
所以就有了这个程序可以正常运行的现象,但是我们一定得避免这样,养成一个良好的习惯素养。

在这里插入图片描述
例二:

#include<iostream>
#include<string>
using namespace std;
int *get10(){
int a=10;
int *b=&a;
return b;
}
int *get20(){
int a=20;
int *b=&a;
return b;	
}
int main(){
int *c10=get10();
int *c20=get10();
cout<<"get10的值,应该为10"<<*c10<<endl;
cout<<"get20的值,应该为20"<<*c20<<endl;
}

//这时就出现错误了。
在这里插入图片描述

问题的解决办法:作为全局变量,直接把地址传入被调函数。
例:

void add_x_to_Array(int array[],int x){
 array[i]=array[i]+x;
 }
 int main(){
 int array[1]={100};
add_x_to_Array(array,10);//直接将地址传入,让调用的函数直接根据指针去原数据快中去修改数据。

2.再讲讲引用返回(直接返回对象本身,不去再复制临时对象)

通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。C++ 函数可以返回一个引用,方式与返回一个指针类似。

当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:
#include <iostream>
using namespace std;
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};//全局变量
const double& setValues( int i )  //在函数名前加个引用号&即可,写法类似与指针,但是指针那种得在主函数中将承接返回值的变量设置为指针类型。
{//加上const后,函数的返回值在主函数中就不能被随意修改。
  return vals[i];   // 返回第 i 个元素的引用
}
 
// 要调用上面定义函数的主函数
int main ()
{
   cout << "改变前的值" << endl;
   for ( int i = 0; i < 5; i++ )
   {
       cout << "vals[" << i << "] = ";
       cout << vals[i] << endl;
   }
 
   setValues(1) = 20.23; // 改变第 2 个元素
   setValues(3) = 70.8;  // 改变第 4 个元素
 
   cout << "改变后的值" << endl;
   for ( int i = 0; i < 5; i++ )
   {
       cout << "vals[" << i << "] = ";
       cout << vals[i] << endl;//完成了对全局变量的修改
   }
   return 0;
}

在这里插入图片描述

**总结:我们必须理解底层的机理,可以有利于提高程序的运行效率,让代码变得更加健壮,
临时对象的一开一销很浪费内存,所以我们要尽可能的去除。**                                
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值