【问题标题】:What's the difference between call by reference and copy/restore引用调用和复制/恢复有什么区别
【发布时间】:2012-02-09 12:40:58
【问题描述】:

引用调用和复制/恢复的结果有什么区别?

背景:我目前正在研究分布式系统。关于远程过程调用的引用参数的传递,该书指出:“引用调用已被复制/恢复所取代。虽然这并不总是相同的,但已经足够了”。我了解通过引用调用和复制/恢复原则上是如何工作的,但我看不出结果的差异可能在哪里?

【问题讨论】:

  • 虽然我能够接受你的回答,但我不得不再等几个小时才能获得赏金。感谢您的出色回答,赏金当然是您的!
  • 啊,我不知道赏金系统。很高兴知道!

标签: terminology parameter-passing rpc


【解决方案1】:

示例取自here

主要代码:

#include <stdio.h>

  int a;

  int main() {
      a = 3;
      f( 4, &a );
      printf("&#37;d\n", a);
      return 0;
  }

按值调用:

f(int x, int &y){
    // x will be 3 as passed argument
    x += a;
    // now a is added to x so x will be 6
    // but now nothing is done with x anymore
    a += 2*y;
    // a is still 3 so the result is 11
}

传入的是值,对传入的变量的值没有影响。

参考调用:

f(int x, int &y){
    // x will be 3 as passed argument
    x += a;
    // now a is added to x so x will be 6
    // but because & is used x is the same as a
    // meaning if you change x it will change a
    a += 2*y;
    // a is now 6 so the result is 14
}

引用传入。实际上函数中的变量与外部的变量相同。

调用复制/恢复:

int a;
void unsafe(int x) {
    x= 2; //a is still 1
    a= 0; //a is now 0
}//function ends so the value of x is now stored in a -> value of a is now 2

int main() {
    a= 1;
    unsafe(a); //when this ends the value of a will be 2
    printf("%d\n", a); //prints 2
}

传入的值对传入的变量的值没有影响,直到函数结束,此时函数变量的FINAL值存储在传入的变量中。

引用调用和复制/恢复之间的基本区别在于,对函数变量所做的更改直到函数结束后才会显示在传入的变量中,而引用调用的更改将立即看到。

【讨论】:

  • 你在他们两个中都使用了&amp;y
  • 在“Call with Copy/Restore”示例中,它打印的是 '0' 而不是 '2'。
  • @Carlochess 你用的是哪种支持复制/恢复的语言?
  • 我真的不明白这个答案是如何被接受和 14 票赞成的。我一定有什么问题。值调用和引用代码都相同,只是 cmets 不同。在两者中,x 都不能是 6,而是 7,因为 4 被传递给 f()。如果我错了,请告诉我。
  • @Mahesha999 你的意思是语法没有改变吗?这都是伪代码,大致看起来像 C。C 根本不支持复制/恢复,所以不要太拘泥于语法。假设在每种情况下,声明的调用参数行为都成立。
【解决方案2】:

通过复制/恢复调用是通过引用调用的一种特殊情况,其中提供的引用对调用者来说是唯一的。引用值的最终结果将在函数结束之前保存。

当 RPC 中的方法通过引用调用时,这种类型的调用很有用。实际数据发送到服务器端,最终结果将发送到客户端。这将减少流量,因为服务器不会每次都更新引用。

【讨论】:

    【解决方案3】:

    参考调用:
    在按引用调用中,我们传递一个指向被调用函数的指针。该指针指向的数据发生的任何更改都会立即反映出来。
    假设如果要对该数据进行大量更改,虽然在本地不会产生太多成本,但在网络成本方面会很昂贵,因为每个更改数据都必须复制回客户端。
    C 代码

     void addTwo(int *arr, int n){
      for(int i=0;i<n;i++){
        arr[i]+=2;  //change is happening in the original data as well
      }
    }
     int main(){
      int arr[100]={1,2,3,...}; // assuming it to be initialised
      addTwo(arr,100);  
    }
    

    通过复制/恢复调用:
    在 call-by-copy/restore 中,其思想是当引用数据调用函数时,只有对数据所做的更改的最终结果被复制回原始数据(当函数即将return) 在函数调用过程中不对原始数据做任何更改,只需要一次传输回客户端。
    在下面的C 代码中,将arr 指向的数据复制到函数中,并在本地数据的所有更改完成后存储回arr
    C 代码

     void addTwo(int *arr, int n){
      // copy data locally
      larr = (int*)malloc(n*sizeof(int));
      for(int i=0;i<n;i++){
        larr[i]=arr[i]; 
      }
      for(int i=0;i<n;i++){
        // change is happening to the local variable larr
        larr[i]+=2;  
      }
      //copy all the changes made to the local variable back to the original data
      for(int i=0;i<n;i++){
        arr[i]=larr[i]; 
      }
    }
    
     int main(){
      int arr[100]={1,2,3,...}; // assuming it to be initialised
      addTwo(arr,100);  
    }
    

    注意:上面显示的代码并不代表实际的 RPC 实现,只是对概念的说明。在真正的 RPC 中,消息中传递的是完整的数据,而不是指针(地址)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-23
      • 2013-02-13
      • 2011-04-26
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多