目录
返回栈变量
引用做函数值,下面三个函数分别设定为不同的返回类型。 分别是返回一个值,返回一个引用,返回一个指针:
int getAA1()
{
int a ;
a = 10;
return a;
}
//返回a的本身 返回a的一个副本 10
int& getAA2()
{
int a ; //如果返回栈上的 引用, 有可能会有问题
a = 10;
return a;
}
int* getAA3()
{
int a ;
a = 10;
return &a;
}
void main1101()
{
int a1 = 0;
int a2 = 0;
a1 = getAA1();
a2 = getAA2(); //10
int &a3 = getAA2(); //若返回栈变量 不能成为其它引用的初始值
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3); // *a3
cout<<"hello..."<<endl;
system("pause");
return ;
}
用debug模式下,运行:
用release模式下,运行:
a3又不是个乱码了!?程序因为不同的版本所运行的结果不一样,这说明程序存在潜在的bug。那么,下面来进行分析:
a1的内存空间分配就不说了;直接说a2,a2是通过引用来返回函数返回值的,而引用的本质是编译器帮程序员直接返回对应的地址,即直接就把a的地址给返回出来,把a的值也给返回出来(可以理解成,是对a的地址和变量,都作了一个副本),a运行完毕之后,在被调函数中的a的运行空间,就不需要了,析构,但通过引用进行了返回,返回一个a的引用,就是返回一个a的本身,即返回a的内存空间;再看a3,返回的是一个引用,用一个引用去接,编译器会把getAA2()的返回值(a的地址),相当于a3这个变量里面,存放的是“oxaa11”,但是,当我们打印a3的时候,编译器,一看a3是个引用,就会执行"*a3",编译器顺着a3的地址去访问,发现对应的位置,已经在被调函数运行结束的时候,都被清掉了,所以,打印出来的是一个乱码。
C++引用使用时的难点:
结论:当函数返回值为引用时,若返回栈变量,不能成为其它引用的初始值,不能作为左值使用,只能作为右值。
返回全局变量
在看当返回值是全局变量的时候:
//变量是static 或者是 全局变量
int j1()
{
static int a = 10;
a ++ ;
return a;
}
int& j2()
{
static int a = 10;
a ++ ;
return a;
}
//若返回静态变量或全局变量
// 可以成为其他引用的初始值
// 即可作为右值使用,也可作为左值使用
void main1112()
{
int a1 = 10;
int a2 = 20;
a1 = j1();
a2 = j2();
int &a3 = j2();
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3);
system("pause");
}
和之前的状况不一样,可以运行出结果,且不会乱码。
返回静态变量
函数当左值且为静态变量的时候:
//--- 函数当左值
//返回变量的值
int g1()
{
static int a = 10;
a ++ ;
return a; //
}
//返回变量本身 , 就是返回所表示的内存空间
int& g2()
{
static int a = 10;
a ++ ;
printf("a:%d \n" , a);
return a;
}
void main()
{
// g1() = 100; 左操作数必须当左值
//11 = 100;
g2() = 100; //函数返回值是一个引用,并且当左值
g2();
int c1 = g1(); //函数返回值是一个引用,并且当右值
int c2 = g2(); //函数返回值是一个引用,并且当右值
//a = 100;
system("pause");
}
"g2() = 100;"这句话,相当于"a = 100",因为g2返回的是变量本身,而变量本身是表示的一段内存空间。所以,是可以运行成功的,这种类型的就是函数返回值是个引用当左值。最主要的看内存空间是不是一个有效的内存空间,本例中的“static int a = 10;”是一个有效的内存空间,不会随被调函数析构而清除。
结论:若返回静态变量或全局变量,可以成为其他引用的初始值,既可作为右值使用,也可作为左值使用,C++链式编程中,经常用到引用,运算符重载专题。
总体代码
dm11_函数返回值是一个引用.cpp
#include <iostream>
using namespace std;
int getAA1()
{
int a ;
a = 10;
return a;
}
//返回a的本身 返回a的一个副本 10
int& getAA2()
{
int a ; //如果返回栈上的 引用, 有可能会有问题
a = 10;
return a;
}
int* getAA3()
{
int a ;
a = 10;
return &a;
}
void main1101()
{
int a1 = 0;
int a2 = 0;
a1 = getAA1();
a2 = getAA2(); //10
int &a3 = getAA2(); //若返回栈变量 不能成为其它引用的初始值
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3); // *a3
cout<<"hello..."<<endl;
system("pause");
return ;
}
//变量是static 或者是 全局变量
int j1()
{
static int a = 10;
a ++ ;
return a;
}
int& j2()
{
static int a = 10;
a ++ ;
return a;
}
//若返回静态变量或全局变量
// 可以成为其他引用的初始值
// 即可作为右值使用,也可作为左值使用
void main1112()
{
int a1 = 10;
int a2 = 20;
a1 = j1();
a2 = j2();
int &a3 = j2();
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3);
system("pause");
}
//////////////////////////////////////////////////////////////////////////
//--- 函数当左值
//返回变量的值
int g1()
{
static int a = 10;
a ++ ;
return a; //
}
//返回变量本身 ,
int& g2()
{
static int a = 10;
a ++ ;
printf("a:%d \n" , a);
return a;
}
void main()
{
// g1() = 100;
//11 = 100;
g2() = 100; //函数返回值是一个引用,并且当左值
g2();
int c1 = g1(); //函数返回值是一个引用,并且当右值
int c2 = g2(); //函数返回值是一个引用,并且当右值
//a = 100;
system("pause");
}