首先我们需要知道的是,当返回一个值,指针,引用时(小于八个字节均可以由寄存器带出)
需要注意的是,由于举例,下面的例子中返回了局部变量的地址,而这是有风险的,不能返回临时的局部的地址或引用。仅供思路分析的参考
1.返回内置类型的值,引用,指针,分别用指针,值,引用接收的情况。
1)通过寄存器返回一个值
2)通过寄存器带出,返回一个指针。
3)返回引用时需要解引用,返回指针时只需要返回一个地址,
4)由于是寄存器返回的值不可取地址,而定义引用变量的右边必须可取地址,如果非要使用引用就需要使用常引用。不能用一个指针接受这个函数的返回值。这个例子是错误的。
5)
返回了一个整型值,用引用接收。
常引用在函数调用完成后产生临时量。
临时量存放在dword[ebp-8]处。
6)通过常指针引用来引用一个寄存器返回的地址,会产生一个临时量。
7)返回一个引用时,返回的时候寄存器带回的是地址,在主函数栈帧时,会自动解引用。那么引用就是引用了value这个变量。value可取地址。
也可以写成int *p =&GetIntRef();
p指向的是value的地址。
2.返回自定义类型的值,引用,指针,分别用指针,值,引用接收的情况。
/****自定义类型返回值时才会产生临时量。返回指针不会产生临时量,返回引用的时候,它自身会解引用****/
//返回自定义类型的值时,分别用指针,值,引用来接收的情况
//自定义一个类型DATA
typedef struct _DATA
{
int a;
}DATA;
DATA GetData()
{
DATA data={10};
return data;
}
int main()
{
//正确,返回值由寄存器带回的
DATA ret1=GetData();
//正确,这里要注意,虽然通过寄存器带回,这里返回的是自定义类型的值,引用时编译器会自动产生一个临时量,而内置类型不可以
DATA &ret2=GetData();
//VC认为不能指向自定义类型返回的(取地址在先,临时量在后),而vs和gcc均支持指针指向自定义类型寄存器带出的返回值 (当然VC是相对比较老的编译器,我们以VS和gcc为准,这是正确的)
DATA *ret3=&GetData();
return 0;
}
//返回自定义类型的指针时,分别用指针,引用来接收的情况
typedef struct _DATA
{
int a;
}DATA;
DATA* GetDataPtr()
{
static DATA data={10};
return &data;
}
int main()
{
//可以
DATA *ret1=&GetDataPtr();
//不可以,返回指针时,跟类型无关,指针跟编译器位数有关,指针永远通过寄存器返回,引用时使用常引用
DATA *&ret2=GetDataPtr();
return 0;
}
//返回自定义类型的引用时,分别用指针,引用来接收的情况
typedef struct _DATA
{
int a;
}DATA;
DATA& GetDataPtr()
{
static DATA data={10};
return data;
}
int main()
{
//可以,这里引用的是寄存器带回的解引用之后的变量值
DATA &ret1=GetDataPtr();
//可以
DATA *ret2=&GetDataPtr();
//不可以,这里等式右边的是寄存器带回的是一个常量,需要用const引用
DATA *&ret3=&GetDataPtr();
//const引用
DATA *const &ret3=&GetDataPtr()
return 0;
}
int *& GetIntPtr()//错误 ,能不能返回引用就看return之后的是否可取地址
{
static int value=10;
return &value;//寄存器带回的一个地址
}
int *const& GetIntPtr()//正确 返回常引用
{
static int value=10;
return &value;
}
int*& GetIntPtr()//正确
{
static int value=10;
static int *ptr=&value;
return ptr; //可取地址
}
DATA *GetDataPtr()
{
static DATA data={10};
return &data;
}
int main()
{
return 0;
}