首页 > 其他分享 >函数返回值与指向对象的指针和引用

函数返回值与指向对象的指针和引用

时间:2023-06-02 20:44:31浏览次数:47  
标签:返回 函数 指向 int 引用 返回值 指针

定义一个指向对象的指针或则引用不会调用构造函数和析构函数。

  

首先,强调一点,和函数传参一样,函数返回时也会做一个拷贝。从某种角度上看,和传参一样,也分为三种:

(1)返回值:返回任意类型的数据类型,会将返回数据做一个拷贝(副本)赋值给变量(return语句后边的变量会生成一个副本给一个临时量,这个临时量会将返回值带给主调函数,当调用点处的表达式结束后该临时变量就被释放掉了,而且定义函数时指定的返回值类型实际上指定的就是这个临时变量的类型。还值得注意的一点是临时量没有具体的内存地址,也就是它都根本没有装值的地方,因此不能被修改,你想去改也不知道去哪里改,所以他是一个右值);由于需要拷贝,所以对于复杂对象这种方式效率比较低(在返回类类型时,没有返回值优化的时候,临时量会通过拷贝构造函数拷贝函数中定义的局部对象,在临时量被释放掉时会调用析构函数;如果是返回值优化,则不会生成临时量,该局部变量的值会直接放在调用点处等号左侧的变量的内存中。);例如:int test(){}或者 Point test(){}
(2)返回指针:返回一个指针,也叫指针类型的函数。

 

1 int* test02()
2 {
3     static int a=0;
4     return &a;
5 }

 

在上面的程序中,函数返回的是局部变量的地址值,它是一个值,因此是右值。

 

1 int* fun()
2 {
3     static int a = 0;
4     cout << &a << endl;
5     static int* p = &a;
6     return p;
7 }

 

在上面的程序中,函数返回的是p指向的地址值,它是一个值,因此是右值。

并且返回类类型的指针的时候不会调用拷贝构造函数和析构函数;例如:int *test(){} 或者 Point *test(){}。如果返回局部变量的指针,则在调用点等号右侧的指针会因为函数内部局部变量的内存释放而变成野指针。对于X64系统来讲,可能会在第一次打印输出的时候打印出局部变量的值。因为函数调用返回后栈上的数据并没有被清空,而是程序失去了对栈所在内存的控制权第二次输出的时候已经被别的数据覆盖了,所以输出的内容是不可控的。

注意:

  • 函数返回的指针是临时量是右值
  • 不要将非静态局部地址用作函数返回值:因为局部地址在离开函数后就失效了。
  • 可以在函数中用动态内存分配(new)的地址返回,但需要注意内存分配和释放不在同一级别,不要忘记释放,否则内存泄露(堆区内存程序员忘记释放,以后再也是用不了这块内存);
  • 可以在主调函数中定义数组,函数中对该数组进行操作,然后返回其中一个元素的地址;

(3)返回引用:返回一个引用,也叫返回引用类型的函数,在返回时会返回局部变量的别名,可以认为函数在返回的时候创建了一个引用,该引用就是局部变量的别名,可以对它修改,因此是右值;

 

 1 int& fun()
 2 {
 3     static int a = 0;
 4     return a;
 5 }
 6 
 7 int main()
 8 {
 9     cout << fun() << endl;
10     fun() = 100;
11     cout << fun() << endl;
12     system("pause");
13     return 0;
14 }

 

运行结果:

 

 但如果返回的是局部变量的引用:

 1 int& fun()
 2 {
 3     int a = 10;
 4     return a;
 5 }
 6 
 7 int main()
 8 {
 9     cout << fun() << endl;
10     fun() = 100;
11     cout << fun() << endl;//再一次调用时fun()的局部变量被重新初始化
12     system("pause");
13     return 0;
14 }

 

同时,该引用不会调用拷贝构造函数和析构函数;例如:int &test(){}或者 Point &test(){}

如果返回值是指针或则引用,栈局部对象会被释放掉,就会出现临时的指针或则引用失去指向的对象,变成野指针(这里姑且认为引用是一个指针常量),会出现不可预料的问题

 

(3)返回字符串:

 

通过 char* s = “Hello”; 的方式得到的是一个字符串常量 Hello,存放在只读数据段(相当于常量,在程序运行的时候不会被释放)把该字符串常量的只读数据段的首地址赋值给了指针 s,所以函数返回时,该字符串常量所在的内存不会被回收,所以能正确地通过指针访问。

 

 1 #include <iostream>
 2 using namespace std;
 3  
 4 char *fun1() {
 5   char *s="hello";
 6   return s;//ok
 7 }
 8  
 9 int main() {
10   char *c1 = fun1();
11   cout<<c1<<endl;
12   //常量,无法在修改 
13   
14   return 0;
15 }

参考文章:

(84条消息) C++函数返回值_赶路人儿的博客-CSDN博客

 

标签:返回,函数,指向,int,引用,返回值,指针
From: https://www.cnblogs.com/Sandals-little/p/17449220.html

相关文章

  • 双指针|三数之和
    ......
  • Spring Boot实现xml传参和返回值
    阅读文本大概需要3分钟。    虽然json作为数据传输的格式大型其道,但是使用xml格式传输的系统还是在一些存量的系统中存在。另外WebService本身就是使用xml格式进行数据传输。今天用个小例子看看SpringBoot如何实现xml传参和返回值。1、新建maven项目,添加依赖1.<projectxm......
  • C语言——指针
    指针的优点:使程序更简洁、紧凑、高效有效的表达更复杂的数据结构动态分配内存得到多于一个数的函数返回值1.指针的基本用法1.1指针的概念内存地址:内存中每个字节单位都有一个编号(一般用十六进制表示)指针:指针就是内存地址指针变量:用于存放地址的变量就叫做指针变量指针变量画图展......
  • C++面试八股文:C++中指针、引用、解引用和取地址有什么不同?
    某日小二参加XXX科技公司的C++工程师开发岗位2面:面试官:指针、引用、解引用和取地址是C++中的重要概念,请问它们在语法和语义上有所不同?小二:指针是一个变量,它存储了一个内存地址。小二:引用是一个别名,它允许使用一个变量的多个名称来访问同一个内存位置。小二:解引用是指使用*运......
  • 二级指针内存模型
    二级指针做输出模型#define_CRT_SECURE_NO_WARNINGS#include<stdlib.h>#include<string.h>#include<stdio.h>//指针做输出:被调用函数分配内存-----OK//指针做输入:主调用函数分配内存//求文件中的两段话的长度intgetMem(char**myp1,int*mylen1,char**myp2,in......
  • 二级指针与const
    二维数组分配:#include<iostream>intmain(){introws=3;intcols=4;//使用二级指针创建一个动态分配的二维数组int**array=newint*[rows];for(inti=0;i<rows;i++){array[i]=newint[cols];}//给数组赋值intcount=0;......
  • EBP、ESP作用——esp始终指向栈顶,ebp是在堆栈中寻址用的(就是临时变量嘛)
    基本概念:(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。—————————————————————以......
  • 双指针算法模板和一些题目
    什么是同向双指针?什么是相向双指针?双指针的鼻祖题——两数之和TwoSum链表上的快慢指针算法快速排序&归并排序 同向双指针•相向双指针•几乎所有TwoSum变种•Partition•QuickSelect•分成两个部分•分成三个部分•一些你没听过的(但是面试会考的)......
  • C++指针需要知道的小细节
    一、定义和赋值一个普通对象intival=1024;如上述代码所示,将ival定义为一个int对象,并给予初始值1024。二、指针对象的声明int*pi;1、如上述代码所示,当定义/声明某个特定类型的指针时,要在类型名称后加一个*号。2、在这里,pi是int类型对象的指针。三、指针的初始值int*......
  • python获取threading多线程的return返回值
    转载:(15条消息)python获取threading多线程的return返回值_pythonthreading返回值_星火燎愿的博客-CSDN博客我们正常使用threading模块创建的线程是无法获取它所执行方法的返回值的;如:w=threading.Thread(target=worker,args=(i,))一、重写线程,获取线程return返回值要想获......