精华内容
下载资源
问答
  • C/C++ 函数参数传递:传值,传指针,传引用(C语言不支持传引用
    千次阅读
    2020-08-01 06:54:01

    函数调用者如何将参数传递给被调用者是有讲究的。 总的来说,函数参数传递分为3种情况:传值,传指针和传引用。

    首先,理解一下实参与形参的概念。
    int func(int x)//x是形参
    {
        return x*x;
    }
    int main(void)
    {
        int a = 10;
        func(a);//a是实参
        return 0;

    上面的代码中,x是形参,a是实参。形参x是实参a的一个拷贝。&a和&x完全不同。

    一,传值

    所谓传值,顾名思义,就是把实参的值直接传递给函数。因为形参是实参的拷贝,所以传值无法改变实参。在C++里面,如果传递的是对象, 那么,在传值过程中,还会隐式的调用对象的拷贝构造函数,有一定的计算执行开销(相当于创建了一个临时对象,函数调用完成后执行临时对象的析构函数)。
    void func(int x)//func采用了传值的形式
    {
        x = x+1;
        printf("x=%d\n", x);
    }
    int main(void)
    {
        int a = 0;
        func(a);//传值不能修改a的值
        printf("a=%d\n", a);
        return 0;
    }
    分析:上面的程序采用了传值的参数传递形式,把a的值0传递给了func函数,而由于x是a的一个拷贝(&a和&x完全不同),因此,x=x+1值修改了x的值 并没有修改a的值。所以上面程序执行的结果,输出为:
    x=1
    a=0

    二,传指针

    传指针就是把实参的地址传递给函数,该地址指向的位置所存储的内容,返回后,该地址的内容发生变化,但不能修改该地址本身,或者让指针指向其他位置。传指针可以修改实参的值,在C++里也不会存在调用对象的拷贝构造函数的问题, 传指针的效率比传值要高。所以,如果需要修改实参的值,就不能传值,而需要传指针等。
    但是,传指针比传值复杂,指针计算一旦移动出了正常范围,会造成程序的非法访问等。
    void func(int *x)//func采用了传指针的形式
    {
        *x = *x+1;
        printf("*x=%d,x=%p,&x=%p\n", *x,x,&x);
    }
    int main(void)
    {
        int a = 0;
        func(&a);//把实参a的地址传递给了函数func
        printf("a=%d,&a=%p\n", a,&a);
        return 0;
    }
    分析:传指针可以修改实参的值,但不能修改指针本身的值(修改无效)。根据指针的定义,*x就是a,所以,*x=*x+1,即为a = a+1,所以上面的代码输出结果为:
    *x=1
    a=1

    传指针,其实也是一种值传递,只不过这个值是一个地址,也就是说如果在调用函数func()中传进去的是变量a的地址0x1234,在函数func()中,实际上是另外临时申请了一个指针变量x,x的值是0x1234,相当于把a的地址赋值给了x,但x本身的地址和a没有任务关系,在函数中,可以修改地址0x1234存储的内容,比如原来是0,可以修改成1,但是你不能把0x1234这个地址给改了,也就是比如你想让x=0x2345,这在函数func()中是没有错的,但是修改后,x的值是0x2345,也就是它指向了另外一个地址,修改的也是0x2345这个位置的内容,就和0x1234没有任何关系了,函数返回后,因为a的地址仍然是0x1234,因为在func()中修改的是0x2345,所以和a没有任何关系。

    三,传引用--C语言不支持
    所谓引用其实就是变量的一个别名。传引用是C++里面引入的一种参数传递方法。传引用实际上也是传递的实参的指针,所以能够修改实参的值。 但是,引用的特性告诉我们,一旦引用初始化后,这个引用就不能再改变。所以,传递引用实际上是拥有传值的方便简单,也同时 具备了传指针的高效,又没传指针的危险,相对安全。

    void func(int &x)//func采用了传引用的形式
    {
        x = x+1;
        printf("x=%d\n", x);
    }
    int main(void)
    {
        int a = 0;
        func(a);//把实参a的引用传递给了函数func
        printf("a=%d\n", a);
        return 0;
    }
    分析:func采用传引用的方法定义,实参a引用传递给函数func之后,func能够修改实参的值。所以上面的程序执行结果为:
    x=1
    a=1
    总之:传值不能修改实参,且如果是对象,效率较低;传指针能够修改实参,效率较高,但容易出错;传引用能够修改实参,效率较高,而且不易出错。

    更多相关内容
  • 主要介绍了Python参数传递机制传值和传引用原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 在本篇文章里小编给大家整理的是关于php传值和传引用的区别点总结,需要的朋友们可以参考下。
  • 主要是对Java方法传值和传引用问题进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
  • 本文实例分析了php5.4传引用时报错问题。分享给大家供大家参考,具体如下: php5.3系列版本以及以前版本,传引用没有什么问题,升级到php5.4以后,传引用的地方,全报错 Fatal error: Call-time pass-by-reference ...
  • 指针传引用

    万次阅读 2021-07-19 17:47:22
    (通过地址值进行引用然后完成交换) 图右边是代码的在栈帧的的一个交换过程: 大概说一下: 首先初始化的main方法在栈帧 有两个内存空间 分别为0xaa00和0xbb00对应a和b的变量地址 然后运行到调用swap2 产生栈帧空间...

    ath9SL
    上图中main方法中声明了a和b两个变量,然后通过swap2方法完成值交换。很简单的过程。(通过地址值进行引用然后完成交换)

    图右边是代码的在栈帧的的一个交换过程:

    大概说一下:

    1. 首先初始化的main方法在栈帧 有两个内存空间 分别为0xaa000xbb00对应a和b的变量地址
    2. 然后运行到调用swap2 产生栈帧空间,空间内 有x和y两个变量形参。
    3. 然后swap2(&a,&b) 去地址值的方式把a和b的地址给了swap2方法 ,
    4. swap2方法 的*x,*y=*y,*x是做了一个值交换,首先第一个*x是取内存空间(我们之前说过 :等号左边的变量,代表变量所指向的内存空间)这里通俗来说就是*x是去main方法的栈帧下取到a的地址值(0xaa00)。
    5. 第三个*y是根据地址把值取(等号右边的变量,代表变量内存空间存储的数据值)到然后赋值给*x(0xaa00),取得的值为20 转化一下:0xaa00=20

    一通百通

    再来一个demo

    主要看 new, new这个关键字是去(heap)堆内存申请一块内存空间,下面var p=new(*int)申请指针类型的内存 ,返回的是一块内存空间的地址值为0xc00001e090 ,想要给它赋值就必须进行取到0xc00001e090地址的空间*p,然后赋值*p=&i ,这个时候根据*p取得值是i的地址0xc0000be008值不是数据值,想要取得i的值需要再加个*就是**p,才能取到i的值。绕的一笔

    func main() {
        var p =new(*int) //p 0xc00001e090
    	var i int
    	i=1000
    	*p=&i
    	fmt.Println(&i) //	0xc0000be008  i地址值
    	fmt.Println(*p) //  0xc0000be008    i地址值
      fmt.Println(p)  //0xc00001e090     p变量的内存地址值
      fmt.Println(**p) // 1000          i的数据值1000
    }
    
    展开全文
  • 传值和传引用-我和LabVIEW:一个NI工程师的编程经验
  • 一、 引用 1.1 引用概念 引用(reference)是为变量起了另一个名字,而不是定义一个新变量。编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。其使用形式如下: 类型& 引用变量名...

    一、 引用

    1.1 引用概念

            引用(reference)是为变量起了另一个名字,而不是定义一个新变量。编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。其使用形式如下:

            类型& 引用变量名(对象名) = 引用实体;

            eg:

    int ival = 1024;
    int &refVal = ival; // refVal 指向ival(是ival的另一个名字)
    int &refVal2;    // 报错:引用必须被初始化

          定义引用时,程序把引用和它的初始化绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,所以引用必须初始化。注意:引用类型必须和引用实体是同种类型的。

    1.2 引用的特性

               (1)  引用在定义式必须初始化;

             (2)一个变量可以有多个引用;

             (3)引用一旦引用一个实体,再不能引用其他实体;

    1.3 引用的使用场景

         1 做参数

    void Swap(int& left, int& right)
    {
    int temp = left;
    left = right;
    right = temp;
    }

         2 做返回值

    int& Count()
    {
    static int n = 0;
    n++;
    // ...
    return n;
    }

           注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

      例如下面代码就会出现问题。

    int& Add(int a, int b)
    {
    	int c = a + b;
    	return c;
    }
    int main()
    {
    	int& ret = Add(1, 2);
    	Add(3, 4);
    	cout << "Add(1, 2) is :" << ret << endl;
    	system("pause");
    	return 0;
    }
    
    
    运行结果:
    Add(1, 2) is :7
    请按任意键继续. . .

               所以使用时注意作用域。

    二、 传值和传引用的效率对比

        先用以下代码进行测试一下:

    #include <time.h>
    #include <iostream>
    using namespace std;
    
    struct A { int a[10000]; };
    void TestFunc1(A a) {}  // 传值
    void TestFunc2(A& a) {}  // 传引用
    A a;
    A Fun3() {
    	return a;
    }
    
    A &Fun4() {
    	return a;
    }
    
    
    void test1()
    {
    	A a;
    	// 以值作为函数参数
    	size_t begin1 = clock();
    	for (size_t i = 0; i < 100000; ++i)
    		TestFunc1(a);
    	size_t end1 = clock();
    
    	// 以引用作为函数参数
    	size_t begin2 = clock();
    	for (size_t i = 0; i < 100000; ++i)
    		TestFunc2(a);
    	size_t end2 = clock();
    	// 分别计算两个函数运行结束后的时间
    	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
    	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
    
    	// 以值作为函数返回值
    	size_t begin3 = clock();
    	for (size_t i = 0; i < 100000; ++i)
    		Fun3();
    	size_t end3 = clock();
    	// 以引用作为函数返回值
    	size_t begin4 = clock();
    	for (size_t i = 0; i < 100000; ++i)
    		Fun4();
    	size_t end4 = clock();
    	// 分别计算两个函数运行结束后的时间
    	cout << "Fun3 time:" << end3 - begin3 << endl;
    	cout << "Fun4 time:" << end4 - begin4 << endl;
    }
    
    int main()
    {
    
    	test1();
    	system("pause");
    	return 0;
    }
    
    
    运行结果:
    TestFunc1(A)-time:129    <-- 参数传值
    TestFunc2(A&)-time:2     <-- 参数传引用
    Fun3 time:336            <-- 返回值为值
    Fun4 time:2              <-- 返回值为引用
    请按任意键继续. . .

          从运行结果可见传引用比传值的效率高很多。因为,以值做为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

    三、 引用和指针的区别

         在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。但是在底层实现上,引用是按指针的方式实现的。怎么体现呢,看汇编代码。如下:

    int main()
    {
        int a = 10;
        int& ra = a;
        ra = 20;
        int* pa = &a;
        *pa = 20;
        return 0;
    }

           将上面简单代码进行反汇编:

    可见:

             在底层实现上:引用通过指针实现,定义一个引用类型变量相当于定义一个指针类型变量

             语法上: 引用是别名,不是指针,没有发生拷贝。

    引用和指针的不同点:
         1. 引用在定义时必须初始化,指针没有要求
         2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
         3. 没有NULL引用,但有NULL指针
         4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
         5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
         6. 有多级指针,但是没有多级引用
         7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
         8. 引用比指针使用起来相对更安全

    展开全文
  • C++传引用和传值,传指针

    千次阅读 2018-10-12 18:53:19
    我们需要数据而不改变数据存储,直接传值,如int a; 我们需要数据,并且改变值大小,需要地址,如 int * pa; 我们需要数据,并改变数结构中指针的指向,需要二级指针,如链表中的 node * * l; ... ...

    我们需要传数据而不改变数据存储,直接传值,如int a;

    我们需要传数据,并且改变值大小,需要传地址,如  int * pa;

    我们需要传数据,并改变数结构中指针的指向,需要传二级指针,如链表中的 node * * l;

    ...

    这是c语言中传值的形式。参考我之前的一篇文章https://blog.csdn.net/weixin_41143631/article/details/82717506

    以前是passl-by-value,而c++在c11中,引入了pass-by-reference,也就是传引用。c++需要一个标识符&。

    给出下面代码

    void my_swap(int* x, int* y)
    {
    	*x = *x^*y;
    	*y = *x^*y;
    	*x = *x^*y;
    	cout << "函数中参数x的地址    " << &x << endl;
    }
    void my_swap(int&a, int&b)
    {
    	a = a^b;
    	b = a^b;
    	a = a^b;
    	cout <<"函数中参数a的地址     "<< &a<< endl;
    
    }
    int main()
    {
    	int www = 1;
    	int a = 0; int b = 100;
    	int x = 0;   int y = 100;
    	my_swap(&x, &y);
    	my_swap(a, b);
    	cout << a << "     主函数 a 的地址   "<<&a<<endl;
    	cout << x << "  主函数x的地址  " <<&x<< endl;
    }

    前者swap是传值(生成拷贝,传地址),而后者直接是传引用,形参和实参的本质是一样,引用只是一个别名。

    运行结果如下

    可以明显看到,这2个重载函数中使用传指针,所指向的地址是不同的,而使用传引用,所指向的地址是相同的。

    传引用:被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    传值:被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。

    int a=0;  //定义a是一个int类变量
    int& ra=a;  //声明ra是a的“引用”,变量ra具有变量a的地址
    
    //引用不能在引用的基础上再引用。

    顺便说一下,gcc在编译时,O2级别优化,传引用,和传地址的汇编代码是一样的。

    在微软的vc编译器(vs2013)运行时,直接优化,传引用,和传地址的汇编代码是一样的。

    所以在我们写代码时,传引用,传指针都可以,不过我自己也趋向于写引用,在c++的模板中也大量使用引用,从制度上完善代码规范,能防微杜渐。

    下面说一下,传引用,和我们常说的“传指针”之间的一些小区别。

    A,传引用需要初始化,指针不需要(但指针推荐每次都初始化,即使无值,也初始化为NULL)。

    B,使用sizeof对其求大小不一样,引用是对应数据的实际大小,而指针则依据机器固定为相应大小(32位为4字节)。

    C,指针更加灵活,++,--可以来访问,而引用没有这些。有多级指针,没有多级引用。

    D,引用相当于和被引用者“绑定”,而指针可以不断改变。

    ...

    从安全的角度,引用能替代指针,这个在很多高级语言,不论是解释性语言还是编译语言中都得到了体现。

    但维持c++的灵活,我们依然可以使用指针,不过推荐使用引用。

     

     

    展开全文
  • 引用的定义:引用是给另外一个变量其别名,所以引用不会分配内存空间,引用是引入了对象的一个同义词。 例如: Point pt1(10,10); Point &pt2 = pt1; 上述的代码,定义了pt2为pt1的引用。通过这样的定义,pt...
  • 传值, 是把实参的值赋值给行参 那么对行参的修改,不会影响实参的... 传引用 真正的以地址的方式传递参数 传递以后,行参和实参都是同一个对象,只是他们名字不同而已 对行参的修改将影响实参的值 ---------...
  • Python传值还是传引用

    千次阅读 2019-04-19 15:09:38
    Python传值还是传引用 1、Python可变对象与不可变对象 不可变对象:该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址...
  • C++中传值传指针传引用的区别

    千次阅读 多人点赞 2019-02-28 17:59:28
    当调用函数时,传递的参数有传值、传指针、传引用这三种形式。 直接传值是直接开辟了一个跟主函数实参一样的空间(地址不一样),里面存放了了跟实参一样大小的值,就相当于数值大小相同但是位置不同。你在这个调用...
  • 传值,传指针和传引用区别和联系

    万次阅读 多人点赞 2016-11-27 12:15:28
    竟然自己发现对传值,传指针,传引用这个每天都在用的传递方式的区别还不是很清楚。以为自己懂了,其实还理解得还不够深入,基础还需要花时间琢磨。今天参考了很多篇博客和书籍做些总结。其实,不用分为三类,只有两...
  • 什么时候传值什么时候传引用? 答: 按值传递:函数范围内对值的任何改变在函数外部都会被忽略 按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改 优缺点:按值传递时,php必须复制值。特别是...
  • 42.传值和传引用.doc
  • 引用类型:严格来说不能算传引用,在js中叫按共享传递 call by sharing也叫按对象传递、按对象共享传递。该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递...
  • PHP传值和传引用区别

    千次阅读 2018-08-08 14:39:51
    传值和传引用、传地址的区别: 1、传值,是把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 2、传地址 是传值的一种特殊方式,只是他传递的是地址,不是普通的如int 那么传地址以后,实参和行参都指向同一...
  • 传引用与传值的区别

    2020-03-19 22:51:58
    传引用:当一个变量的值赋予另外一个变量时,改动新的变量将影响原始的变量;使用引用赋值,简单的就是将&符号加到将要赋值的 变量前;相当于别名; 对象默认是传引用; 使用场景:对于较...
  • 其实无论是传值还是传引用调用,其本质都是将栈中存储的数据复制一份,传递给栈中的另一个变量。对于基础数据类型,是将数据本身复制一份传递;对于引用类型,是将引用的地址复制一份传递。因此,上述问题可以描述为...
  • golang传值和传引用

    千次阅读 2019-01-02 09:53:04
    golang传值和传引用 这里不会解释关于指针的情况,如果读者对C语言或者C++的指针比较了解,那么就能更好地理解本文。 定义 对于代码 modify(a); a.modify(); 如果modify中对于a的修改不会改变传入的a的值,那么就是...
  • vue子父组件传引用类型

    千次阅读 多人点赞 2020-06-20 21:59:04
    简单描述一下引用类型复制的特点: 引用类型:把值和地址想成比作面包和面包存放的地址。 复制引用类型的浅复制:A拥有面包和面包的地址,然后将A复制给B,那么B只是知道了面包存放的地址。 复制引用类型的深复制:...
  • 实参: 1.如果是基本数据类型和String,则实参不会改变,因为的是值。 2.但如果的是对象集合或者数组,就会改变,因为的是引用
  • 彻底搞明白传值,传地址,传引用

    千次阅读 2020-07-11 22:22:53
    传引用是真正的以地址的方式传递参数, 传递以后,行参和实参都是同一个对象,只是名字不同而已,对行参的修改将影响实参的值。 4.在python中的情况 python不允许程序员选择采用传值还是传引用。Python参数传递采用...
  • C++ 传值和传引用的效率对比

    千次阅读 2020-02-09 18:25:35
    条款22: 尽量用“传引用”而不用“传值” c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它作为默认方式。除非明确指定,函数的形参总是通过“实参的拷贝”(拷贝构造函数)来初始化的,函数的调用者得到...
  • vec),传引用 function3(vector *vec),传指针 注意,三种方式分别有对应的const形式,不在此讨论。 三种方式对应的调用形式分别为: function1(vec),传入值 function2(vec),传入引用 function3(&vec),传入...
  • 首先,不要纠结于 Pass By Value 和 Pass By Reference 的字面上的意义,否则很容易陷入所谓的“一切传引用其实本质上是传值”这种并不能解决问题无意义论战中。更何况,要想知道Java到底是传值还是传引用,起码你要...
  • 传地址调用和传引用调用的区别

    千次阅读 2017-09-05 21:13:17
    传地址调用和传引用调用的区别相同点: 传引用和传地址,原理上都是将参数变量的地址传递给被调函数。所以在函数内部修改参数的值时,均可返回修改之后的结果给调用者。 不同点: 引用一定会指向一个对象,而指针...
  • C++语言的传递方式:传值,传地址,传引用。没记错的话C++98之后传引用才可以用。 第一种方式: 传值:就是拷贝一份数据给,数据量小无所谓,数据量大,这个不推荐,效率很慢的。 示例:第一个fun函数。典型的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 415,451
精华内容 166,180
关键字:

传引用

友情链接: 电流检测.zip