精华内容
下载资源
问答
  • C语言参数传递的三种方式

    千次阅读 2020-09-04 14:11:38
    C语言中函数参数传递的三种方式 (1)传值,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值。 (2)传址,就是传变量的...

    C语言中函数参数传递的三种方式

    (1)传值,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值。
    (2)传址,就是传变量的地址赋给函数里形式参数的指针,使指针指向真实的变量的地址,因为对指针所指地址的内容的改变能反映到函数外,也就是能改变函数外的变量的值。
    (3)传引用,实际是通过指针来实现的,能达到使用的效果如传址,可是使用方式如传值。
    说几点建议:如果传值的话,会生成新的对象,花费时间和空间,而在退出函数的时候,又会销毁该对象,花费时间和空间。
    因而如果int,char等固有类型,而是你自己定义的类或结构等,都建议传指针或引用,因为他们不会创建新的对象。

    例1:下面这段代码的输出结果为:

    //引用交换
    void swip(int &a, int &b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    //值传递
    void swip1(int a, int b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    	cout << "swip1 a = " << a << "swip1 b = " << b << endl;
    }
    //地址传递值传递
    void swip2(int *a, int *b)
    {
    	int temp = *a;
    	*a = *b;
    	*b = temp;
    }
    int main()
    {
    	int a = 10, b = 20;
    	swip1(a, b);
    	cout << "a = " << a << "b = " << b <<endl;
    	system("pause");
    	return 0;
    }
    

    解析:
    该题考察函数传参问题。
    1,指针传参 -> 将变量的地址直接传入函数,函数中可以对其值进行修改。
    2,引用传参 -> 将变量的引用传入函数,效果和指针相同,同样函数中可以对其值进行修改。
    3,值传参 -> 在传参过程中,首先将c的值复制给函数c变量,然后在函数中修改的即是函数的c变量,然后函数返回时,系统自动释放变量c。而对main函数的c没有影响。

    转载:https://blog.csdn.net/weibo1230123/article/details/75541862

    展开全文
  • C++中函数调用时的三种参数传递方式详解

    万次阅读 多人点赞 2017-08-31 20:44:51
    原文地址:http://blog.csdn.net/cocohufei/article/details/6143476;  ...   在C++中,参数传递方式是“实虚结合”。 按值传递(pass by value) 地址传递(pass by pointer) 引用传递(pass b...

    原文地址:http://blog.csdn.net/cocohufei/article/details/6143476; 

    http://blog.chinaunix.net/uid-21411227-id-1826834.html

     

    在C++中,参数传递的方式是“实虚结合”。

    • 按值传递(pass by value)
    • 地址传递(pass by pointer)
    • 引用传递(pass by reference)

    按值传递的过程为:首先计算出实参表达式的值,接着给对应的形参变量分配一个存储空间,该空间的大小等于该形参类型的,然后把以求出的实参表达式的值一一存入到形参变量分配的存储空间中,成为形参变量的初值,供被调用函数执行时使用。这种传递是把实参表达式的值传送给对应的形参变量,故称这种传递方式为“按值传递”。

    使用这种方式,调用函数本身不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。

    /* 
      pass By value 
    */  
    #include <iostream>  
    using namespace std;  
    void swap(int,int);  
    int main()  
    {  
        int a = 3, b = 4;  
        cout << "a = " << a << ", b = "  
        << b << endl;  
        swap(a,b);  
        cout << "a = " << a << ", b = "  
        << b << endl;  
        return 0;  
    }  
    void swap(int x, int y)  
    {  
         int t = x;  
         x = y;  
         y = t;  
    }  
    

    输出:

    如果在函数定义时将形参说明成指针,对这样的函数进行调用时就需要指定地址值形式的实参。这时的参数传递方式就是地址传递方式。

    地址传递与按值传递的不同在于,它把实参的存储地址传送给对应的形参,从而使得形参指针和实参指针指向同一个地址。因此,被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。

    #include <iostream>
    
    using namespace std;
    
    void swap(int*, int*);
    int main(){
    	int a = 3, b = 4;
    	cout << "a=" << a << ", b=" << b << endl;
    	swap(&a, &b);
    	cout << "a=" << a << ", b=" << b << endl;
    	system("pause");
    	return 0;
    }
    
    void swap(int *x, int *y){
    	int t = *x;
    	*x = *y;
    	*y = t;
    }

    输出:

    按值传递方式容易理解,但形参值的改变不能对实参产生影响。

    地址传递方式虽然可以使得形参的改变对相应的实参有效,但如果在函数中反复利用指针进行间接访问,会使程序容易产生错误且难以阅读。

    如果以引用为参数,则既可以使得对形参的任何操作都能改变相应的数据,又使得函数调用显得方便、自然。引用传递方式是在函数定义时在形参前面加上引用运算符“&”。

    #include <iostream>
    
    using namespace std;
    
    void swap(int&, int&);
    int main(){
    	int a = 3, b = 4;
    	cout << "a=" << a << ", b=" << b << endl;
    	swap(a, b);
    	cout << "a=" << a << ", b=" << b << endl;
    	system("pause");
    	return 0;
    }
    
    void swap(int &x, int &y){
    	int t = x;
    	x = y;
    	y = t;
    }

    输出:

     

    一、 函数参数传递机制的基本理论

      函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。

      值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

      引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    二、 C语言中的函数参数传递机制

      在C语言中,值传递是唯一可用的参数传递机制。但是据笔者所知,由于受指针变量作为函数参数的影响,有许多朋友还认为这种情况是引用传递。这是错误的。请看下面的代码:

    #include <iostream>
    
    using namespace std;
    
    int swap(int *x, int *y)
    {
    	int temp;
    	temp = *x; 
    	*x = *y; 
    	*y = temp;
    	return temp;
    }
    
    void main()
    {
    
    	int a = 1, b = 2;
    	int *p1 = &a;
    	int *p2 = &b;
    	swap(p1, p2);
    }

      函数swap以两个指针变量作为参数,当main()调用swap时,是以值传递的方式将指针变量p1、p2的值(也就是变量a、b的地址)放在了swap在堆栈中为形式参数x、y开辟的内存单元中。

     这里我们可以得到以下几点:

      1. 进程的堆栈存储区是主调函数和被调函数进行通信的主要区域。

      2. C语言中参数是从右向左进栈的。

      3. 被调函数使用的堆栈区域结构为:

        局部变量(如temp)

        返回地址

        函数参数

        低地址

        高地址

      4. 由主调函数在调用后清理堆栈。

      5. 函数的返回值一般是放在寄存器中的。

      这里尚需补充说明几点:一是参数进栈的方式。对于内部类型,由于编译器知道各类型变量使用的内存大小故直接使用push指令;对于自定义的类型(如structure),采用从源地址向目的(堆栈区)地址进行字节传送的方式入栈。二是函数返回值为什么一般放在寄存器中,这主要是为了支持中断;如果放在堆栈中有可能因为中断而被覆盖。三是函数的返回值如果很大,则从堆栈向存放返回值的地址单元(由主调函数在调用前将此地址压栈提供给被调函数)进行字节传送,以达到返回的目的。对于第二和第三点,《Thinking in C++》一书在第10章有比较好的阐述。四是一个显而易见的结论,如果在被调函数中返回局部变量的地址是毫无意义的;因为局部变量存于堆栈中,调用结束后堆栈将被清理,这些地址就变得无效了。

    三、 C++语言中的函数参数传递机制

       众所周知,在c++中调用函数时有三种参数传递方式:

     (1)传值调用;

     (2)传址调用(传指针);

     (3)引用传递;

        实际上,还有一种参数传递方式,就是全局变量传递方式。这里的“全局”变量并不见得就是真正的全局的,所有代码都可以直接访问的,只要这个变量的作用域足够这两个函数访问就可以了,比如一个类中的两个成员函数可以使用一个成员变量实现参数传递,或者使用static关键字定义,或者使用namespace进行限制等,而这里的成员变量在这种意义上就可以称作是“全局”变量(暂时还没有其它比“全局”更好的词来描述)。当然,可以使用一个类外的真正的全局变量来实现参数传递,但有时并没有必要,从工程上讲,作用域越小越好。这种方式有什么优点呢?

     效率高!

     的确,这种效率是所有参数传递方式中效率最高的,比前面三种方式都要高,无论在什么情况下。但这种方式有一个致命的弱点,那就是对多线程的支持不好,如果两个进程同时调用同一个函数,而通过全局变量进行传递参数,该函数就不能够总是得到想要的结果。

     

     下面再分别讨论上面三种函数传递方式。

        1. 从功能上。按值传递在传递的时候,实参被复制了一份,然后在函数体内使用,函数体内修改参数变量时修改的是实参的一份拷贝,而实参本身是没有改变的,所以如果想在调用的函数中修改实参的值,使用值传递是不能达到目的的,这时只能使用引用或指针传递。例如,要实现两个数值交换。

     void swap(int a  int b) 

     void main(){

         int a=1  b=2 

         swap(a b) 

     }

     这样,在main()函数中的a b值实际上并没有交换,如果想要交换只能使用指针传递或引用传递,如:

     void swap(int *a  int *b) 

     或

     void swap(int &a  int &b)

     

       2.从传递效率上。这里所说传递效率,是说调用被调函数的代码将实参传递到被调函数体内的过程,正如上面代码中,这个过程就是函数main()中的a b传递到函数swap()中的过程。这个效率不能一概而论。对于内建的int  char   short long float等4字节或以下的数据类型而言,实际上传递时也只需要传递1-4个字节,而使用指针传递时在32位cpu中传递的是32位的指针,4个字节,都是一条指令,这种情况下值传递和指针传递的效率是一样的,而传递double  long long等8字节的数据时,在32位cpu中,其传值效率比传递指针要慢,因为8个字节需要2次取完。而在64位的cpu上,传值和传址的效率是一样的。再说引用传递,这个要看编译器具体实现,引用传递最显然的实现方式是使用指针,这种情况下与指针的效率是一样的,而有些情况下编译器是可以优化的,采用直接寻址的方式,这种情况下,效率比传值调用和传址调用都要快,与上面说的采用全局变量方式传递的效率相当。

         再说自定义的数据类型,class  struct定义的数据类型。这些数据类型在进行传值调用时生成临时对象会执行构造函数,而且当临时对象销毁时会执行析构函数,如果构造函数和析构函数执行的任务比较多,或者传递的对象尺寸比较大,那么传值调用的消耗就比较大。这种情况下,采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说,某些情况下引用传递可能被优化,总体效率稍高于传址调用。

        3. 从执行效率上讲。这里所说的执行效率,是指在被调用的函数体内执行时的效率。因为传值调用时,当值被传到函数体内,临时对象生成以后,所有的执行任务都是通过直接寻址的方式执行的,而指针和大多数情况下的引用则是以间接寻址的方式执行的,所以实际的执行效率会比传值调用要低。如果函数体内对参数传过来的变量进行操作比较频繁,执行总次数又多的情况下,传址调用和大多数情况下的引用参数传递会造成比较明显的执行效率损失。

     综合2、3两种情况,具体的执行效率要结合实际情况,通过比较传递过程的资源消耗和执行函数体消耗之和来选择哪种情况比较合适。而就引用传递和指针传递的效率上比,引用传递的效率始终不低于指针传递,所以从这种意义上讲,在c++中进行参数传递时优先使用引用传递而不是指针。

        4. 从类型安全上讲。值传递与引用传递在参数传递过程中都执行强类型检查,而指针传递的类型检查较弱,特别地,如果参数被声明为 void ,那么它基本上没有类型检查,只要是指针,编译器就认为是合法的,所以这给bug的产生制造了机会,使程序的健壮性稍差,如果没有必要,就使用值传递和引用传递,最好不用指针传递,更好地利用编译器的类型检查,使得我们有更少的出错机会,以增加代码的健壮性。

     这里有个特殊情况,就是对于多态的情况,如果形参是父类,而实参是子类,在进行值传递的时候,临时对象构造时只会构造父类的部分,是一个纯粹的父类对象,而不会构造子类的任何特有的部分,因为办有虚的析构函数,而没有虚的构造函数,这一点是要注意的。如果想在被调函数中通过调用虚函数获得一些子类特有的行为,这是不能实现的。

     5. 从参数检查上讲。一个健壮的函数,总会对传递来的参数进行参数检查,保证输入数据的合法性,以防止对数据的破坏并且更好地控制程序按期望的方向运行,在这种情况下使用值传递比使用指针传递要安全得多,因为你不可能传一个不存在的值给值参数或引用参数,而使用指针就可能,很可能传来的是一个非法的地址(没有初始化,指向已经delete掉的对象的指针等)。所以使用值传递和引用传递会使你的代码更健壮,具体是使用引用还是使用,最简单的一个原则就是看传递的是不是内建的数据类型,对内建的数据类型优先使用值传递,而对于自定义的数据类型,特别是传递较大的对象,那么请使用引用传递。

        6. 从灵活性上。无疑,指针是最灵活的,因为指针除了可以像值传递和引用传递那样传递一个特定类型的对象外,还可以传递空指针,不传递任何对象。指针的这种优点使它大有用武之地,比如标准库里的time( )函数,你可以传递一个指针给它,把时间值填到指定的地址,你也可以传递一个空指针而只要返回值。

     

    以上讨论了四种参数传递方式的优缺点,下面再讨论一下在参数传递过程中一些共同的有用的技术。

     1. const关键字。当你的参数是作为输入参数时,你总不希望你的输入参数被修改,否则有可能产生逻辑错误,这时可以在声明函数时在参数前加上const关键字,防止在实现时意外修改函数输入,对于使用你的代码的程序员也可以告诉他们这个参数是输入,而不加const关键字的参数也可能是输出。例如strlen,你可以这样声明

         int strlen(char str) 

     功能上肯定没有什么问题,但是你想告诉使用该函数的人,参数str是一个输入参数,它指向的数据是不能被修改的,这也是他们期望的,总不会有人希望在请人给他数钱的时候,里面有张100的变成10块的了,或者真钞变成假钞了,他们希望有一个保证,说该函数不会破坏你的任何数据,声明按如下方式便可让他们放心:

         int strlen(const char str) 

     可不可以给str本身也加一个限制呢,如果把地址改了数得的结果不就错了吗?总得给人点儿自由吧,只要它帮你数钱就行了,何必介意他怎么数呢?只要不破坏你的钱就ok了,如果给str一个限制,就会出现问题了,按照上面的声明,可以这样实现:

    int strlen(const char str){    
    	int cnt;
    	if(!str) 
    		return 0;
    	cnt = 0;
    	while((str++)){
    		++cnt; 
    	}
    	return cnt;
    
    }

     可是,如果你硬要把声明改成

         int strlen(const char const str) 

     上面的函数肯定就运行不了了,只能改用其它的实现方式,但这个不是太有必要。只要我们保护好我们的钱就行了,如果它数不对,下次我次不让它数,再换个人就是了。

     

    对于成员函数,如果我们要显示给客户代码说某个成员函数不会修改该对象的值,只会读取某些内容,也可以在该函数声明中加一个const.

     class    person

     {......

       public:

         unsigned char age( void ) const   // 看到const就放心了,这个函数肯定不会修改m_age

       private:

         unsigned char m_age    // 我认为这个类型已经足够长了,如果觉得不改可以改为unsigned long

     }

         2. 默认值。个人认为给参数添加一个默认值是一个很方便的特性,非常好用,这样你就可以定义一个具有好几个参数的函数,然后给那些不常用的参数一些默认值,客户代码如果认为那些默认值正是他们想要的,调用函数时只需要填一些必要的实参就行了,非常方便,这样就省去了重载好几个函数的麻烦。可是我不明白c#为什么把这个特性给去掉了,可能是为了安全,这样就要求每次调用函数时都要显示地给函数赋实参。所以要注意,这可是个双刃剑,如果想用使刀的招跟对手武斗,很可能伤到自己。

        3.参数顺序。当同个函数名有不同参数时,如果有相同的参数尽量要把参数放在同一位置上,以方便客户端代码。

    c++ 中经常使用的是常量引用,如将swap2改为:

        Swap2(const int& x; const int& y)

      这时将不能在函数中修改引用地址所指向的内容,具体来说,x和y将不能出现在"="的左边。

     

     

     

    展开全文
  • 函数参数三种传递方式的区别

    万次阅读 2017-01-07 13:47:00
    问题提出:1、当一个类的对象作为实参数传递时,使用值传递和引用传递什么区别? 比如: DateType ExampleFun(CString &strFileName,…)与 DateType ExampleFun(CString strFileName,…)解答之前,我们先来看2...

    函数参数三种传递方式的区别

    问题提出:

    1、当一个类的对象作为实参数传递时,使用值传递和引用传递有什么区别?
    比如: DateType ExampleFun(CString &strFileName,…)与
    DateType ExampleFun(CString strFileName,…)

    解答之前,我们先来看2个基本的概念:形参和实参。

    ->通俗的讲:形参是形式上的参数,实参是实际的参数;
    ->详细的讲:形参只是对实参的一种抽象类型描述,只是声明一个函数(方法)能接受什么类型的实参,而不确定接受的实参具体内容是多少;

    实参就是传递给函数(方法)对应形参的具体内容(值),形参的初始指(内容)由实参决定.形参在函数(方法)结束返回后就被释放了.

    现在进入主题:参数传递方式分:传值和传址;
    1.传值方式,只是将实参的值的拷贝传递给函数(方法),在方法内对形参进行操作,其对象是实参的拷贝,对实参不能造成影响.在方法结束返回后,形参被释放丢弃,实参的内容并不会改变;

    2.传址方式,将实参的地址传递给函数(方法),在方法内对形参进行操作即等于对实参进行相同的操作,在方法结束返回后,形参同样被释放,实参的内容将会是对形参进行操作的结果.

    而传址方式,又可以细分为:引用传递(pass-by-reference) , 指针传递(pass-by-pointer)

    引用其实就是对象的别名,传对象的引用,用于把一个对象的地址作为参数传过去,而不是对象本身。

    这是我们就明白了前面问题的答案:传递引用,避免了一次实参到形参的拷贝,提高了效率。

    使用引用参数的原因:
    1. 程序员能够修改调用函数中的数据对象

    1. 通过传递引用而不是整个数据对象,可以提高程序的运行速度。

      当数据对象较大时(如结构和类对象),第二个原因最重要,这些也是使用指针参数的原因。这是有道理的,因为引用参数实际上是基于指针的代码的另一个接口。

    那么什么时候使用引用、什么时候使用指针?什么时候又应该按值传递呢?下面是一些指导原则:

    对于使用传递值而不做修改的函数:

    1. 如果数据对象较小,如内置数据类型或者小型结构,则按值传递。

    2. 如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针。

    3. 如果数据对象是较大的结构,则使用const指针或const引用,以提高运行效率。这样可以节省复制结构所需的时间和空间。

    4. 如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++增加引用特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。

    对于修改调用函数中数据的函数:

    1. 如果数据对象是内置数据类型,则是用指针。如果看到诸如fixit(&x)这样的代码(其中x是int型),则很明显,该函数将修改x。

    2. 如果数据对象是数组,则只能使用指针。

    3. 如果数据对象是结构,则使用引用或指针。

    4. 如果数据对象是类对象,则使用引用。

    当然,这只是一些指导原则,很可能有充分的理由做出其他的选择。如:对于基本类型,cin使用引用。因此可以使用cin>>n, 而不是cin>>&n 。

    另外找了其他的资料:

    1.

    什么是“引用”?申明和使用“引用”要注意哪些问题?

    引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。

    申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。

    会调用拷贝构造函数和析构函数

    A a(){…;return *this;}
    A& a(){…;return *this;}
    不会调用拷贝构造函数和析构函数
    应该都能够作为左值

    当返回一个变量时,会产生拷贝。当返回一个引用时,不会发生拷贝,你可以将引用看作是一个变量的别名,就是其他的名字,引用和被引用的变量其实是一个东西,只是有了两个名字而已。

    问题的关键是,当你想要返回一个引用而不是一个拷贝时,你要确保这个引用的有效性,比如:
    int & fun() { int a; a=10; return a; }
    这样是不行的,因为a会在fun退出时被销毁,这时返回的a的引用是无效的。
    这种情况下,如果fun的返回类型不是int & 而是int就没有问题了。

    因此,要返回一个引用时,“临时变量”不能是“临时”的,至少得等函数外部使用完毕这个引用之后,才能销毁它。

    2.返回引用的好处:

    1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

    (2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。

    (3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用”*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

    3 在什么时候需要使用“常引用”?

    如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;

    例1

    int a ;

    const int &ra=a;

    ra=1; //错误

    a=1; //正确

    例2

    string foo( );

    void bar(string & s);

    那么下面的表达式将是非法的:

    bar(foo( ));

    bar(“hello world”);

    原因在于foo( )和”hello world”串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。

    引用型参数应该在能被定义为const的情况下,尽量定义为const 。

    1. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?

    格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }

    好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!

    注意事项:

    (1)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。

    (2)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。

    (3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

    (4)流操作符重载返回值申明为“引用”的作用:

    流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << “hello” << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

    例3

    #include

    展开全文
  • 函数参数传递的三种方式

    千次阅读 2019-05-15 20:28:58
    C语言中函数参数传递的三种方式 (1)传值,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值。 (2)传址,就是传变量的...

    C语言中函数参数传递的三种方式

    (1)传值,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值。
    (2)传址,就是传变量的地址赋给函数里形式参数的指针,使指针指向真实的变量的地址,因为对指针所指地址的内容的改变能反映到函数外,也就是能改变函数外的变量的值。
    (3)传引用,实际是通过指针来实现的,能达到使用的效果如传址,可是使用方式如传值。
    说几点建议:如果传值的话,会生成新的对象,花费时间和空间,而在退出函数的时候,又会销毁该对象,花费时间和空间。
    因而如果int,char等固有类型,而是你自己定义的类或结构等,都建议传指针或引用,因为他们不会创建新的对象。

    例1:下面这段代码的输出结果为:
    #include<stdio.h>
    void change(int*a, int&b, int c)
    {
    c=*a;
    b=30;
    *a=20;
    }
    int main ( )
    {
    int a=10, b=20, c=30;
    change(&a,b,c);
    printf(“%d,%d,%d,”,a,b,c);
    return 0;
    }
    结果:20 30 30

    解析:
    该题考察函数传参问题。
    1,指针传参 -> 将变量的地址直接传入函数,函数中可以对其值进行修改。
    2,引用传参 -> 将变量的引用传入函数,效果和指针相同,同样函数中可以对其值进行修改。
    3,值传参 -> 在传参过程中,首先将c的值复制给函数c变量,然后在函数中修改的即是函数的c变量,然后函数返回时,系统自动释放变量c。而对main函数的c没有影响。

    例2:
    #include<stdio.h>
    void myswap(int x, int y)
    {
    int t;
    t=x;
    x=y;
    y=t;
    }
    int main()
    {
    int a, b;
    printf(“请输入待交换的两个整数:”);
    scanf("%d %d", &a, &b);
    myswap(a,b); //作为对比,直接交换两个整数,显然不行
    printf(“调用交换函数后的结果是:%d 和 %d\n”, a, b);
    return 0;
    }

    #include<stdio.h>
    void myswap(int *p1, int *p2)
    {
    int t;
    t=*p1;
    *p1=*p2;
    *p2=t;
    }
    int main()
    {
    int a, b;
    printf(“请输入待交换的两个整数:”);
    scanf("%d %d", &a, &b);
    myswap(&a,&b); //交换两个整数的地址
    printf(“调用交换函数后的结果是:%d 和 %d\n”, a, b);
    return 0;
    }

    #include<stdio.h>
    void myswap(int &x, int &y)
    {
    int t;
    t=x;
    x=y;
    y=t;
    }

    int main()
    {
    int a, b;
    printf(“请输入待交换的两个整数:”);
    scanf("%d %d", &a, &b);
    myswap(a,b); //直接以变量a和b作为实参交换
    printf(“调用交换函数后的结果是:%d 和 %d\n”, a, b);
    return 0;
    }
    第一个的运行结果:输入2 3,输出2 3
    第二个的运行结果:输入2 3,输出3 2
    第三个的运行结果:输入2 3,输出3 2

    解析:
    在第一个程序中,传值不成功的原因是指在形参上改变了数值,没有在实参上改变数值。
    在第二个程序中,传地址成功的原因利用指针改变了原来的地址,所以实参就交换了。
    在第三个程序中,引用是直接改变两个实参变量a,b的值,所以就交换了。

    下文会通过例子详细说明关于值传递,指针传递,引用传递

    1)值传递:

    形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,
    

    不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。

    2)指针传递:

    形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作
    

    3)引用传递:

    形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
    
    下面的代码对此作出了细致解释(从实参,形参在内存中存放地址的角度 说明了问题的本质,容易理解  )
    

    1 #include
    2 using namespace std;
    3 //值传递
    4 void change1(int n){
    5 cout<<“值传递–函数操作地址”<<&n<<endl; //显示的是拷贝的地址而不是源地址
    6 n++;
    7 }
    8
    9 //引用传递
    10 void change2(int & n){
    11 cout<<“引用传递–函数操作地址”<<&n<<endl;
    12 n++;
    13 }
    14 //指针传递
    15 void change3(int *n){
    16 cout<<"指针传递–函数操作地址 "<<n<<endl;
    17 *n=*n+1;
    18 }
    19 int main(){
    20 int n=10;
    21 cout<<“实参的地址”<<&n<<endl;
    22 change1(n);
    23 cout<<“after change1() n=”<<n<<endl;
    24 change2(n);
    25 cout<<“after change2() n=”<<n<<endl;
    26 change3(&n);
    27 cout<<“after change3() n=”<<n<<endl;
    28 return true;
    29 }
    运行结果如下,(不同的机器可能会有所差别)

    可以看出,实参的地址为0x22ff44

    采用值传递的时候,函数操作的地址是0x22ff20并不是实参本身,所以对它进行操作并不能改变实参的值
    

    再看引用传递,操作地址就是实参地址 ,只是相当于实参的一个别名,对它的操作就是对实参的操作
    接下来是指针传递,也可发现操作地址是实参地址
    那么,引用传递和指针传递有什么区别吗?

    引用的规则:
    引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。

    不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
    一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
    指针传递的实质:

    指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的
    
    任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变)如果理解不了大可跳过这段
    

    指针传递和引用传递一般适用于:

    函数内部修改参数并且希望改动影响调用者。对比指针/引用传递可以将改变由形参“传给”实参(实际上就是直接在实参的内存上修改,不像值传递将实参的值拷贝到另外的内存地址中才修改)。
    
    另外一种用法是:当一个函数实际需要返回多个值,而只能显式返回一个值时,可以将另外需要返回的变量以指针/引用传递给函数,这样在函数内部修改并且返回后,调用者可以拿到被修改过后的变量,也相当于一个隐式的返回值传递吧。
    
    以下是我觉得关于指针和引用写得很不错的文章,大家可参照看一下,原文出处地址:http://xinklabi.iteye.com/blog/653643 
    
    从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。
    
    而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。
    
    在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的:
    
    指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变)
    

    而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。
    

    为了进一步加深大家对指针和引用的区别,下面我从编译的角度来阐述它们之间的区别:

    程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

    最后,总结一下指针和引用的相同点和不同点:

    1)相同点:

    都是地址的概念;
    指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

    2)不同点:

    指针是一个实体,而引用仅是个别名;
    引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
    引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有 的, 前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)
    引用不能为空,指针可以为空;
    “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
    指针和引用的自增(++)运算意义不一样;
    引用是类型安全的,而指针不是 (引用比指针多了类型检查)

    一、引用的概念

    引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。
    例如: Point pt1(10,10);
    Point &pt2=pt1; 定义了pt2为pt1的引用。通过这样的定义,pt1和pt2表示同一对象。
    需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。因此,当下面的语句执行后:
    pt1.offset(2,2);
    pt1和pt2都具有(12,12)的值。
    引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才
    初始化它。例如下面语句是非法的:
    Point &pt3;
    pt3=pt1;
    那么既然引用只是某个东西的同义词,它有什么用途呢?
    下面讨论引用的两个主要用途:作为函数参数以及从函数中返回左值。

    二、引用参数

    1、传递可变参数
    传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。
    所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现
    两整数变量值交换的c程序如下:
    一、引用的概念

    引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。
    例如: Point pt1(10,10);
    Point &pt2=pt1; 定义了pt2为pt1的引用。通过这样的定义,pt1和pt2表示同一对象。
    需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。因此,当下面的语句执行后:
    pt1.offset(2,2);
    pt1和pt2都具有(12,12)的值。
    引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才
    初始化它。例如下面语句是非法的:
    Point &pt3;
    pt3=pt1;
    那么既然引用只是某个东西的同义词,它有什么用途呢?
    下面讨论引用的两个主要用途:作为函数参数以及从函数中返回左值。

    二、引用参数

    1、传递可变参数
    传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。
    所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现
    两整数变量值交换的c程序如下:
    void swapint(int *a,int *b)
    {
    int temp;
    temp=*a;
    a=*b;
    *b=temp;
    }

    使用引用机制后,以上程序的c++版本为:
    void swapint(int &a,int &b)
    {
    int temp;
    temp=a;
    a=b;
    b=temp;
    }
    调用该函数的c++方法为:swapint(x,y); c++自动把x,y的地址作为参数传递给swapint函数。

    2、给函数传递大型对象
    当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的
    副本,也就是参数传递时,对象无须复制。下面的例子定义了一个有限整数集合的类:
    const maxCard=100;
    Class Set
    {
    int elems[maxCard]; // 集和中的元素,maxCard 表示集合中元素个数的最大值。
    int card; // 集合中元素的个数。
    public:
    Set () {card=0;} //构造函数
    friend Set operator * (Set ,Set ) ; //重载运算符号*,用于计算集合的交集 用对象作为传值参数
    // friend Set operator * (Set & ,Set & ) 重载运算符号*,用于计算集合的交集 用对象的引用作为传值参数

    }
    先考虑集合交集的实现
    Set operator ( Set Set1,Set Set2)
    {
    Set res;
    for(int i=0;i<Set1.card;++i)
    for(int j=0;j>Set2.card;++j)
    if(Set1.elems[i]==Set2.elems[j])
    {
    res.elems[res.card++]=Set1.elems[i];
    break;
    }
    return res;
    }
    由于重载运算符不能对指针单独操作,我们必须把运算数声明为 Set 类型而不是 Set * 。
    每次使用
    做交集运算时,整个集合都被复制,这样效率很低。我们可以用引用来避免这种情况。
    Set operator *( Set &Set1,Set &Set2)
    { Set res;
    for(int i=0;i<Set1.card;++i)
    for(int j=0;j>Set2.card;++j)
    if(Set1.elems[i]==Set2.elems[j])
    {
    res.elems[res.card++]=Set1.elems[i];
    break;
    }
    return res;
    }

    三、引用返回值

    如果一个函数返回了引用,那么该函数的调用也可以被赋值。这里有一函数,它拥有两个引用参数并返回一个双精度数的引用:
    double &max(double &d1,double &d2)
    {
    return d1>d2?d1:d2;
    }
    由于max()函数返回一个对双精度数的引用,那么我们就可以用max() 来对其中较大的双精度数加1:
    max(x,y)+=1.0;


    作者:魏波-
    来源:CSDN
    原文:https://blog.csdn.net/weibo1230123/article/details/75541862
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • Matlab的GUI参数传递方式总结

    千次阅读 多人点赞 2019-04-18 21:20:29
    Matlab GUI参数传递 Matlab提供了很多种直接或间接方法实现多fig中的数据共享: 1、全局变量 2、作为函数的参数传递 3、利用控件的userdata数据 4、为handles结构体添加新字段 5、setappdata函数为句柄添加...
  • 参数传递

    千次阅读 2018-12-01 07:30:18
    在Java中参数传递主要分为两种,一是值传递,二是引用传递。 一、首先我们要知道哪些数据类型。  一种是基本数据类型。就是我们熟悉的 byte 、short、int、long、float、double、char、boolean 共八种。  另...
  • SpringBoot前后端分离参数传递方式总结

    千次阅读 多人点赞 2020-11-26 21:39:50
    因为总是需要使用不同的参数传递方式,所以特地来总结一下SpringBoot中常用的传递参数的方式。 SpringBoot参数传递 注意:虽然Restful风格很流行,但是大部分还是主要是GET和POST的内容,所以这里只是列举GET和POST...
  • C语言中函数参数传递的三种方式

    万次阅读 多人点赞 2017-07-22 21:09:40
    C语言中函数参数传递的三种方式(1)传值,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值。(2)传址,就是传变量的地址...
  • C/C++中语言的3种参数传递方式

    万次阅读 多人点赞 2017-09-14 18:30:26
    参数传递,是在程序运行过程中,实际参数就会将参数值传递给相应的形式参数,然后在函数中实现对数据处理和返回的过程,方法3种方式 值传递 地址传递 引用传递 tips: 被调用函数的形参只有函数被调用时才会临时...
  • python中参数传递的方法

    千次阅读 2020-08-13 14:21:15
    Python中函数传递参数的形式主要有以下五种,分别为位置传递,关键字传递,默认值传递,不定参数传递(包裹传递)和解包裹传递。 1.位置传递实例: def fun(a,b,c)  return a+b+c print(f(1,2,3)) 2.关键字...
  • mybatis 传递参数的三种方式

    万次阅读 2017-06-14 11:50:28
    mybatis 框架的主要工作是数据层, 侧重于与...mybatis 传递参数方式主要有三种: 1. 多个参数传递方式  形式如:  GoodMapper.java:  public Good selectGood(String id, String name);  GoodMapper
  • 函数传递参数的三种方式,以及它们的区别1.按值传递(pass by value)使用这种方式,调用函数本省不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。这相当...
  • 在SpringBoot整合Mybatis中,传递多个参数方式和Spring整合Mybatis略微有点不同,下面主要总结三种常用的方式 一、顺序传参法 Mapper层: 传入需要的参数 public interface GoodsMapper { public Goods ...
  • mybatis 传递参数的7种方法

    万次阅读 多人点赞 2019-07-06 10:23:59
    单个参数传递很简单没有什么好将的,这里主要说下多个参数传递 1.第一种方式 匿名参数 顺序传递参数 controller @ApiOperation(value = "多个参数查询_匿名顺序传参") @GetMapping("findByPara...
  • python3 不允许我们选择参数传递方式,但是他已经全部采用了引用传递。 相关测试代码与解释贴在文章里了。
  • Java中参数传递方式(超详细)

    千次阅读 2014-11-21 16:50:32
    无论是什么语言,要讨论参数传递方式,就得从内存模型说起,主要是我个人觉得从内存模型来说参数传递更为直观一些。闲言少叙,下面我们就通过内存模型的方式来讨论一下Java中的参数传递。 这里的内存模型涉及到两种...
  • vue页面间参数传递的方法总结

    千次阅读 2018-11-20 21:20:53
    方法一:通过路由带参数进行传值 方法二:通过设置 Session Storage/local Storage缓存的形式进行传递 1、 原生用法使用 2、 对Session Storage/local Storage缓存进行统一封装 方法三:父子组件之间的传值(通过...
  • C++参数传递的三种方式

    千次阅读 热门讨论 2014-03-30 22:08:06
    一般来说C++中参数传递有三种方式:值传递、指针传递、引用传递 1.值传递——传值 值传递是最常见的一种参数传递方式,但是对初学者来说也最容易出错。如下例: #include void fun(int a,int b) { int temp; ...
  • int * 类型作为形参--值传递:形参p1,p2 也要分配内存空间,实参的值复制给形参(地址) */ void mySwap2(int *p1,int *p2){ //改变形参指针的指向,不会影响到实参 int *temp; temp=p1; p1=p2; p2=temp; } /...
  • 前言 在做 Flutter 开发的时候所有...我们做 Android 开发的人员都知道 Android 应用程序在进行页面跳转的时候可以利用Intent进行参数传递,那么再开发 Flutter 的时候类似的方式可以进行参数传递么?答案当然是...
  • 3种函数参数传递方式

    千次阅读 2014-11-23 14:50:54
    3种函数参数传递方式 1. 将变量名作为形参和实参 在这种情况下传给形参的是变量的值。传递是单向的,即如果在执行函数期间形参的值发生变化,并不传回给实参,这就是值传递方式。因为在调用函数期间,形参和实参...
  • Java基础知识面试题(2020最新版)

    万次阅读 多人点赞 2020-02-19 12:11:27
    原理是什么Java语言哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的主类何不同?Java应用程序与小程序之间那些差别?Java和C++的区别Oracle JDK 和 OpenJDK 的...
  • Hadoop 传递参数的四种方式

    千次阅读 2017-08-24 12:01:38
     这个是mappe task 和reduce task log打印出来的信息,说明参数传递成功  至于其他的基本类型的设置方式与String类型类似,并且其实还是转化为String类型进行存取,例如int型: /** * Set the value...
  • vue-router传递参数的几种方式

    万次阅读 多人点赞 2018-07-06 16:24:29
    vue-router传递参数分为两大类编程式的导航 router.push声明式的导航 &lt;router-link&gt;编程式的导航 router.push编程式导航传递参数有两种类型...对象想要传递参数主要就是以对象的方式来写,分为两种方...
  • Django URL传递参数方式总结

    万次阅读 2018-06-23 23:03:34
    Django URL传递参数方式总结 (django2.0)新建一个Django项目,默认的urls.py文件内容。from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site....
  • websocket之参数传递和依赖注入

    万次阅读 2017-03-14 10:39:00
    我在通过websocket实现这个功能的过程中遇到了2个问题:websocket建立连接时需要传递参数(例如服务器ip,项目名称,日志文件位置等)进去;需要注入service 层的类,以便在onOpen()方法中进行数据查询和业务处理...
  • Mybatis使用之参数传递

    千次阅读 2015-05-20 16:41:24
    摘要: 主要记录Mybatis是如何映射传递的参数的。分四种来记录:1、java基本类型的传递、2、Java对象形式传递 3、多参数传递4、集合类型参数传递
  • 本篇文章主要讲的是JavaScript中最正常不过的现象——函数参数传递,本篇文章篇幅不长,但一定能引发属于你自己的思考!
  • 如果参数传递的数据较大时,建议使用引用作为函数的形参,这样会提高函数的时间效率,并节省内存空间 。 3.使用指针作为函数的形参虽然达到的效果和使用引用一样,但 当调用函数时仍需要为形参指针变量在内存中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 624,036
精华内容 249,614
关键字:

参数的传递方式主要有