zoukankan      html  css  js  c++  java
  • C++ 引用详解

    花了一天的时间来研究引用,引用在C语言里是没有的。它在C++中,是某对象的另一个名字。主要用途是为了描述函数的参数和返回值,特别是为了运算符的重载。

    废话不多说,直接贴代码

    #include "stdafx.h"
    #include <iostream>
    
    int& r_fun_r(int& param)
    {
        int result = param++;
        return result;
    }
    int fun_r(int& param)
    {
        int result = param++;
        return result;
    }
    int& r_fun(int param)
    {
        int result = param++;
        return result;
    }
    int fun(int param)
    {
        int result = param++;
        return result;
    }
    
    int main()
    {
        using namespace std;
        int param_in_main = 1; 
    
        
        int result = r_fun_r(param_in_main);
        cout << result << param_in_main << endl;
        result = r_fun(param_in_main);
        cout << result << param_in_main << endl;
        result = fun_r(param_in_main);
        cout << result << param_in_main << endl;
        result = fun(param_in_main);
        cout << result << param_in_main << endl;
        getchar();
        return 0;
    }

    以上定义了四个函数,分别对应有无传递引用参数,有无返回引用值。

    编译,返回引用值的函数r_fun_r(),r_fun()发出了警告:

    警告 C4172 返回局部变量或临时变量的地址。

    说明了2个问题:一,返回值为一个地址(或者说是个隐藏的指针)。二,即使在函数内部返回的是一个int型变量,编译器也会按照函数声明返回一个地址。

    那么,在main函数中,int result = r_fun_r(param_in_main);这句岂不是将一个地址赋给了一个int型变量?

    继续研究,进入反汇编。原来,

    int result = r_fun_r(param_in_main);
     lea eax,[param_in_main] 
     push eax 
     call r_fun_r (011610B9h) 
     add esp,4
    
     mov ecx,dword ptr [eax] 
    
     mov dword ptr [result],ecx

    函数确实返回了一个地址。编译器讲这个地址的内容取到ECX中,再复制到result变量所在的内存区域中。

    但问题是,这个返回的地址所在的栈空间是r_fun_r()的栈。在call r_fun_r跳转回之后,这个栈已经被释放。此时再访问栈中的数据会有很大的风险。

    所以函数返回的引用必须要在内存空间中已经分配好地址。

    此外,如果使用引用作为函数的传入值和返回值,在函数压栈的时候,压入的是当前参数的地址,返回的也是一个地址。如果不用引用来传入和返回,则压栈时会复制一份参数的值来传参。

    这样如果是大结构的传入返回,就会增加代码的负担,性能降低!反汇编代码如下:

    int result = r_fun_r(param_in_main);
    lea         eax,[param_in_main]  //[]传入地址
    push        eax 
    call ...
    。
    。
    。
    result = r_fun(param_in_main);
    mov         eax,dword ptr [param_in_main]  //传入值!
    push        eax  
    call ...
    。
    。
    。

    关于引用在运算符重载中的使用。以后再看!!

  • 相关阅读:
    通过注册表找网站绝对路径
    西普学院Crypto之用户名和密码
    西普学院Crypto之一段奇怪的代码
    西普学院Crypto之先有鸡还是先有蛋
    西普学院Crypto之摩擦摩擦
    西普学院Crypto之凯撒是罗马共和国杰出的军事统帅
    各类文件的文件头标志[转]
    收藏的几个脑图
    同源策略详解及绕过[转]
    Python学习#1
  • 原文地址:https://www.cnblogs.com/feng-qing-yang/p/5896922.html
Copyright © 2011-2022 走看看