将变量传递给函数时,为什么函数只获得变量的副本?

时间:2012-07-31 08:45:09

标签: c++ c

将变量传递给函数时,为什么函数只获取变量的副本/副本?

int n=1;

void foo(int i)
{
    i++;
}

众所周知,函数foo()不能通过使用foo(n)来改变n的值。

当然我们可以传递变量的地址来对参数变量进行一些更改 但是你不觉得这有点不方便吗?

为什么c / c ++只是为了给函数提供一个副本而不是直接给函数赋予“真实”变量? 这种范式的优点/好处是什么?


更新
我读过@paxdiablo的回答。我认为他的“封装,模块化和效果本地化”的解释是好的 但在我的方式,它也可以保留参数参数的值。它还可以实现封装。通过这种方式:(假设函数可以直接获取“真实”变量而不是默认重复)

void foo(int n)
{
    int temp=n;
    //Do something to temp...

}

在我的方式中,当您想要更改传入的参数值时,复杂的机制,例如“通过引用传递”或指针可以被消除。这就是好处。

经过一段时间的思考。我意识到为什么c / c ++没有像我提出的那样设计的原因仅仅是因为我的方式的不确定性!
按照我的方式,如果一个函数有很长的变量列表,那就太可怕了。我想要的是更方便的方式实际上不方便:
你必须这样写:

void foo(int a,int b,double c,float d,char s...)
{
    int temp1=a;
    int temp2=b;
    double temp3=c;
    float temp4=d;
    char temp5=s;
    ...
    //Do something to temp{1,2,3,4,5....}

}

因此,c / c ++的设计者引入了复杂的机制来方便地进行权衡 我是对的吗?

9 个答案:

答案 0 :(得分:6)

这个问题基本上是两种思想流派。

第一个是pass-by-value,其中为被调用函数创建了值的 copy

第二个是pass-by-reference,其中出现在被调用函数中的参数是原始的“别名”。这意味着您对其所做的更改将反映在原始文件中。

C通常是一种按值传递的语言。您可以通过传递变量的地址来模拟传递引用,然后使用它来修改原始文件:

void setTo42 (int *x) { *x = 42; }
:
int y;
setTo42 (&y);
// y is now 42

但是更多的是通过值将指针传递给变量,而不是通过引用传递变量本身。

C ++有真正的引用类型,可能是因为很多人在使用C指针时出现问题:-)它们完成如下:

void setTo42 (int &x) { x = 42; }

:
int y;
setTo42 (y);
// y is now 42

通过值传递通常是优选的,因为它限制了函数对“外部世界”的影响 - 封装,模块化和效果的本地化通常是一件好事。

在模块化和代码管理方面,能够任意修改传入的任何参数几乎与全局变量一样糟糕。

但是,有时您需要传递引用,因为更改传入的其中一个变量可能是有意义的。

答案 1 :(得分:4)

大多数现代语言都定义为使用pass by value。原因是 简单:如果您知道,它可以显着简化代码的推理 一个函数不能改变你的本地状态。如果想要一个函数能够修改本地状态,你总是可以通过非const引用传递,但是这种情况应该非常罕见。

已编辑以回复更新的问题:

不,你不对。按值传递是传递参数的最简单机制。通过引用传递或复制/复制是更复杂的(当然,Algol的表达替换是最复杂的)。

考虑一下。考虑f(10)。通过按值调用,编译器只是将10推送到堆栈上,并且该函数只是原位访问该值。通过引用调用,编译器必须创建一个临时的,用10初始化它,然后将指针传递给函数。在函数内部,编译器必须在每次访问值时生成间接。

此外,防止功能内部的修改并不能真正帮助提高可读性。如果函数没有引用参数,你就知道它没有在函数内部查看它不能修改你作为参数传递的任何变量。无论人们将来如何修改该功能。 (人们甚至可以争辩说不应该允许函数修改全局状态。这会使rand()的实现变得相当困难。但肯定会有助于优化器。)

答案 2 :(得分:3)

因为C按值传递参数。

来自Kernighan和; Ritchie第2版:( 1.8按值调用)“在C中,所有函数参数都通过”value“”

传递

答案 3 :(得分:2)

如果你真的想要一个函数来改变它的实际参数,你可以通过C ++中的引用传递它

void foo(int& i)
{
    i++;
}

答案 4 :(得分:0)

确保该功能不会改变原始值。

答案 5 :(得分:0)

我猜一个原因是效率,通过指针直接访问值更有效。另一个优点是选择,你可以选择通过值或指针传递参数的C / C ++方式,你只能选择通过指针传递。但最重要的是,通过值传递意味着您的函数与代码的其余部分隔离,并且对函数内部变量的更改不会影响其余代码。相信我你会得到更多的错误,如果不是这样的话,编码将会更加困难。

答案 6 :(得分:0)

要更改参数的值,您需要使用'&'通过引用传递符号

这样做的原因是您可以选择是否要让更改坚持使用您的变量。如果您通过值传递,则可以确保它不会更改并导致程序出错。

答案 7 :(得分:0)

根据您要执行的操作,您可以执行以下操作:

  

int n = 1;

     

n = foo(n);

确保foo(int i)在修改后返回i。

答案 8 :(得分:0)

C值传递的一个原因是在FORTRAN中,它是传递引用,你可以用“CALL MYROUTINE(3)”之类的调用来调用子程序,子程序会更改其参数的值。然后,在程序中的那一点之后,“3”将具有子程序给它的值。

当然,当发生这种情况时,它引起了很大的混乱。它使得很难找到错误,因为源代码做了一些与它看起来完全不同的东西。

因此,随着人们对编程语言的了解,设计语言时使用的原则之一就是避免使代码难以理解或使错误更容易发生的事情。 (这个原则并不总是成功应用,因为我们也倾向于赋予编程语言更强的表达能力,并使编译器能够优化代码。)