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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11736306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:29:15  来源:igfitidea点击:

When pass a variable to a function, why the function only gets a duplicate of the variable?

c++c

提问by duleshi

When pass a variable to a function, why the function only gets a copy/duplicate of the variable?

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

int n=1;

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

As we all know, the function foo() can't change the value of nby using foo(n).

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

Of course we can pass the address of the variable to make some change to the parameter variable.
But don't you think that is a little bit inconvenient?

当然我们可以通过变量的地址来对参数变量做一些改变。
但是你不觉得这有点不方便吗?

Why c/c++ is designed to only give a duplicate to the function instead of directly give the "real" variable itself to the function?
What't the pro/benefit of this paradigm?

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



Update:
I have read @paxdiablo's answer. I think his "encapsulation, modularity and localisation of effect" explanation is good.
But in my way, it can also preserve the parameter argument's value as well. It can also realize encapsulation. By this way:(assume the function can directly get the "real" variable instead of a duplicate by default )

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

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

}

And in my way, the complicated mechanism,such as "pass by reference" or pointer can be eliminatedwhen you do want to change the value of parameters passed in. That's the benifit.

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

After a time of thought. I realise the reason why c/c++ isn't designed as I proposed is just because of the INCONVINIENCE of my way!
In my way, if a function has a long list of variables, it would to terrible. What I thougth is the more convenient way is infact inconvenient:
You must write like this:

经过一段时间的思考。我意识到 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....}

}

So the designers of c/c++ introduce complex mechanism to trade off with convenience.
Am I right?

所以c/c++的设计者引入了复杂的机制来权衡方便。
我对吗?

采纳答案by paxdiablo

The are basically two schools of thought on this matter.

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

The first is pass-by-value where a copyof the value is created for the called function.

第一个是按值传递,其中为被调用函数创建值的副本

The second is pass-by-reference where the parameter that appears in the called function is an "alias" of the original. That means changes you make to it are reflected in the original.

第二种是通过引用传递,其中出现在被调用函数中的参数是原始函数的“别名”。这意味着您对其所做的更改会反映在原始文件中。

C is generally a pass-by-value language. You can emulate pass-by-reference by passing the addressof a variable and then using that to modify the original:

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

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

but that's more passing the pointer to a variable by value, than passing the variable itself by reference.

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

C++ has true reference types, possibly because so many people have trouble with C pointers :-) They're done as follows:

C++ 有真正的引用类型,可能是因为很多人都对 C 指针有问题:-) 他们是这样做的:

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

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

Pass-by-value is usually preferable since it limits the effects that a function can have on the "outside world" - encapsulation, modularity and localisation of effect is usually a good thing.

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

Being able to arbitrarily modify any parameters passed in would be nearly as bad as global variables in terms on modularity and code management.

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

However, sometimes you need pass-by-reference since it might make sense to change one of the variables passed in.

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

回答by James Kanze

Most modern languages are defined to use pass by value. The reason is simple: it significantly simplifies reasoning about the code if you know that a function cannot change your local state. You can always pass by non-const reference if you wanta function to be able to modify local state, but such cases should be extremely rare.

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

EDITED to respond to updated question:

编辑以回答更新的问题:

No, you're not right. Pass by value is the simplest mechanism for passing parameters. Pass by reference or copy-in/copy-out are more complex (and of course, Algol's expression replacement is the most complicated).

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

Think about it for awhile. Consider f(10). With call by value, the compiler just pushes 10on the stack, and the function just accesses the value in situ. With call by reference, the compiler must create a temporary, initialize it with 10, and then pass a pointer to it to the function. Inside the function, the compiler must generate an indirection each time it accesses the value.

想一想。考虑f(10)。通过按值调用,编译器只是压10入堆栈,函数只是在原地访问值。通过引用调用,编译器必须创建一个临时对象,用 初始化它10,然后将指向它的指针传递给函数。在函数内部,编译器每次访问该值时都必须生成一个间接引用。

Also, protecting from modification inside the function doesn't really help readability. If the function takes no reference parameters, you know without looking inside the function that it cannot modify any variables you pass as arguments. Regardless of how anyone modifies the function in the future. (One could even argue that functions should not be allowed to modify global state. Which would make the implementation of rand()rather difficult. But would certainly help the optimizer.)

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

回答by ouah

Because C pass arguments by value.

因为 C 按值传递参数。

From Kernighan & Richtie 2nd edition : (1.8 Call by value) "In C all function arguments are passed by "value""

来自 Kernighan & Richtie 第二版:(1.8 按值调用)“在 C 中,所有函数参数都通过“值”传递”

回答by Andrey

If you really want a function to change its actual parameter, you can pass it by reference in C++

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

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

回答by Jeeva

It is to make sure that the function doesn't change the original value.

这是为了确保函数不会改变原始值。

回答by jahhaj

I guess one reason is efficiency, it's more efficient to access values directly then through a pointer. Another advantage is choice, the C/C++ way you can choose to pass arguments by value or by pointer, your way you only have the choice to pass by pointer. But most importantly passing by value means that your function is isolated from the rest of your code, and changes to variables inside the function don't affect the rest of the code. Believe me you would get far more bugs and coding would be more difficult if this were not the case.

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

回答by Troy Cosentino

In order to change the value of a parameter you need to pass by reference using the '&' symbol.

为了更改参数的值,您需要使用“&”符号通过引用传递。

The reason this is done is so that you can choose whether or not you want changes to stick with your variable. If you pass by value you can be sure that it will not change and cause an error in your program.

这样做的原因是您可以选择是否希望更改与您的变量保持一致。如果您按值传递,您可以确保它不会更改并导致您的程序出错。

回答by fvgs

Depending on what you're trying to do, you can do this:

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

int n = 1;

n = foo(n);

整数 n = 1;

n = foo(n);

Just make sure foo(int i) returns i after modifying it.

只需确保 foo(int i) 在修改后返回 i 即可。

回答by Eric Postpischil

One reason C is pass-by-value is that in FORTRAN, which is pass-by-reference, it was possible that you could call a subroutine with a call like “CALL MYROUTINE(3)”, and the subroutine would change the value of its argument. Then, after that point in the program, “3” would have the value given to it by the subroutine.

C 是按值传递的一个原因是在 FORTRAN 中,它是按引用传递,您可能可以使用类似“CALL MYROUTINE(3)”这样的调用来调用子例程,并且该子例程会更改值其论点。然后,在程序中的那个点之后,“3”将具有子程序赋予它的值。

Naturally, when this occurred, it caused great confusion. It made bugs hard to find, because source code did something very different from what it appeared to do.

自然,当这件事发生时,引起了极大的混乱。它使错误很难找到,因为源代码做了一些与它看起来很不一样的事情。

So, as people have learned about programming languages, one of the principles used in designing languages is to avoid things that made code hard to understand or that made bugs more likely. (This principle is not always successfully applied, as we are also tempted to give programming languages more expressive power and to enable compilers to optimize code.)

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