简体   繁体   English

为什么一个 function 对实际参数的副本进行操作?

[英]Why does a function operates on the copy of the actual parameters?

I want to understand what is happening behind when you pass a parameter by value to a function.我想了解当您将参数按值传递给 function 时发生了什么。 How is this "the function copy the values" done?这个“function 复制值”是如何完成的?

I would like this to be a parallel between passing an array vs passing two variables.我希望这在传递数组与传递两个变量之间是平行的。

I've searched some threads, from which I consider this would best fit, although I have some other question.我搜索了一些线程,我认为是最适合的,尽管我还有其他问题。

Here are two examples:这里有两个例子:

Ex1:例1:

void function(int arr[])
{
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

int main()
{
    int vector[] = {1,2,3,4,5,6,7};
    function(vector);
    return 0;
}

Ex2:例 2:

void interChange(int a, int b)
{
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

int main()
{
    int a = 5, b = 3;
    interChange(a, b);
    return 0;
}

In the first one, I want to show that even if I pass an array by value it is still interpreted as a pointer (allowing modifications in function to alter the actual vector values), this is why printing the array will output an address, and printing its size will output the dimension of a pointer.在第一个中,我想表明,即使我按值传递一个数组,它仍然被解释为一个指针(允许在 function 中修改以改变实际vector ),这就是为什么打印数组将 output 一个地址,并且打印其尺寸将 output 指针的尺寸。

In the second example, the parameters are passed by value, but this time they do not alter the values of variables a and b .在第二个示例中,参数按值传递,但这次它们不会改变变量ab的值。 How does this process take place?这个过程是如何发生的? Why are they copied instead of using their addresses too?为什么他们被复制而不是使用他们的地址呢? Does the compiler take into account something about their addresses?编译器是否考虑到它们的地址? If I print &a in main() and then inside the interChange, I get two addresses very close one to each other Eg: 0x69fed8 , 0x69fe80 .如果我在main()中打印&a ,然后在 interChange 中打印,我会得到两个0x69fe80 0x69fed8

See whenever you pass any argument to any function,generally it gets copied to the function parameter.每当您将任何参数传递给任何 function 时,请查看,通常它会被复制到 function 参数。 But here is an exception in cases of array this thing doesn't happen.但是这里有一个例外,在数组的情况下这件事不会发生。 Whenever you pass array to any function compiler automatically convert it to pointer to first element of the array.每当您将数组传递给任何 function 编译器时,编译器都会自动将其转换为指向数组第一个元素的指针。 Now let's come to two cases现在让我们来看两个案例

Case 1: when you passed an array compiler converted it to pointer to first element of that array.情况 1:当您传递一个数组编译器时,将其转换为指向该数组第一个元素的指针。 Now array of int type so Ofc pointer will be of int type and size of int pointer it 4bytes which you can see.现在是 int 类型的数组,因此 Ofc 指针将是 int 类型,并且 int 指针的大小为 4 字节,您可以看到。

Case 2: when you passed two ints in second function.案例 2:当您在第二个 function 中传递两个整数时。 The passing argument are copied to the function parameter.传递的参数被复制到 function 参数。 So remember whether you write name same in argument and parameter list as you did.因此,请记住您是否在参数和参数列表中写入名称与您所做的相同。 Both are different variables.两者都是不同的变量。 Whatever you do in function will not going to affect to the variables in main.无论您在 function 中做什么,都不会影响 main 中的变量。 So your interchange function is of no use as it is working on A and B of it's own function not on the end which are in main.因此,您的交换 function 没有用,因为它正在处理它自己的 A 和 B 的 function 而不是主要的。

I hope it's clear now.我希望现在很清楚。 Comment if you didn't get any part如果您没有得到任何部分,请发表评论

Ok this is just the convention that C-programming language chose.好的,这只是 C 编程语言选择的约定。 C++ inherited it from C. C++ 继承自 C。

You gave two different but somewhat related examples.你给出了两个不同但有些相关的例子。 I am going to address them separately.我将分别讨论它们。

For the second example : When you declare a variable int a for example - machine need to store a value somewhere.对于第二个示例:例如,当您声明一个变量int a时 - 机器需要在某处存储一个值。 That is there is certain amount of RAM allocated to store a value that can be interpreted as int .也就是说,分配了一定数量的 RAM 来存储可以解释为int的值。 on x86, 32bit machine - this should be 32bit / 4 bytes of memory.在 x86 上,32 位机器 - 这应该是 memory 的 32 位/4 字节。

When a function is called with arguments - values must be passed to a function.当使用 arguments 调用 function 时 - 必须将值传递给 function。 THat is some memory must be allocated to store this values.那就是必须分配一些 memory 来存储这些值。 C and C++ chose to copy values by default. C 和 C++ 默认选择复制值。 That is the fist thing that happens when a function is called - some memory allocated.这是调用 function 时发生的第一件事 - 分配了一些 memory。 for its arguments and values are copied to that new memory.为其 arguments 和值复制到新的 memory。 This works nice for ints as they can be stored in CPU registers - which are limited in size.这对整数很有效,因为它们可以存储在 CPU 寄存器中——它们的大小是有限的。 If you want to modify values - you need to take an address of the memory where a value is stored - pass that address to a function.如果要修改值 - 您需要获取存储值的 memory 的地址 - 将该地址传递给 function。 Note you have at copied the address.请注意,您已复制地址。 But having address - pointer - allows you to change values stored at that address.但是拥有地址 - 指针 - 允许您更改存储在该地址的值。


// Copy two integers
void interChange(int a, int b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

void interChangePtr(int* a, int* b) {
    int tmp;
    tmp = *a;
    a* = *b;
    b* = tmp;
}

int main() {
    int a = 5, b = 3;
    interChange(a, b);
    // a=5, b=3.

    interChangePtr(&a, &b);
    // a=3, b=5

    return 0;
}

As for your second example - this is another convention that C chose.至于您的第二个示例-这是C选择的另一个约定。 When you type:当您键入:

int main() {
 int arr[25]; // Allocates memory on the stack for 25 integers
 ...

Declaring an array (in C-style) informs the compiler that you'd like it to allocate memory for your array on the stack.声明一个数组(以 C 风格)通知编译器您希望它为堆栈上的数组分配 memory。 An array is just a continues chunk of memory.数组只是 memory 的连续块。 So you can take a pointer to it and modify values using that pointer.因此,您可以获取指向它的指针并使用该指针修改值。 And in C if you type arr - this is the pointer to memory allocated for you on the stack.C中,如果您键入arr - 这是在堆栈上为您分配的指向 memory 的指针。 So when you call a function void function(int arr[]) as function(arr) - this actually passes a pointer to your array not the actual block of memory.因此,当您调用 function void function(int arr[]) as function(arr) - 这实际上传递了指向您的数组的指针,而不是 memory 的实际块。 The reason for these conventions - is performance.这些约定的原因 - 是性能。 It is faster to pass a single pointer to an array then to allocate a new array and copy data over.将单个指针传递给数组然后分配新数组并复制数据会更快。

Hope that gives you some pointer to reseach the topic further.希望能给你一些进一步研究这个话题的指导。

Copying by value means in fact the following pattern.按值复制实际上意味着以下模式。

int a = 10;
int b = a;

In this simple example the value of a is copied into the variable b .在这个简单的例子中, a的值被复制到变量b中。

This function declaration from your first example您的第一个示例中的此 function 声明

void function(int arr[]);

is equivalent to the declaration相当于声明

void function(int *arr);

because the compiler implicitly adjusts a parameter having an array type to pointer to the array element type.因为编译器隐式地将具有数组类型的参数调整为指向数组元素类型的指针。

On the other hand, an array passed by value is implicitly converted to pointer to its first element.另一方面,按值传递的数组被隐式转换为指向其第一个元素的指针。

This function definition此 function 定义

void function(int arr[])
{
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

and its call和它的召唤

function(vector);

you can imagine the following way你可以想象以下方式

function(vector);
//...

void function( /*int arr[] */)
{
    int *arr = vector; 
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

That is function parameters are its local variables and if arguments are passed by value then these local variables get copies of the values of the arguments.即 function 参数是它的局部变量,如果 arguments 是按值传递的,那么这些局部变量将获得 arguments 值的副本。

But take into account that elements of an array in fact are passed by reference through the pointer to the first element of the array.但考虑到数组的元素实际上是通过指向数组第一个元素的指针通过引用传递的。

It looks the same way as if you had the following function它看起来就像你有以下 function

void interChange(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

and

interChange( &a, &b);

To show the similarity with the passing an array as an argument that is converted to pointer to its first element you can rewrite the function definition the following way为了显示与将数组作为参数传递并转换为指向其第一个元素的指针的相似性,您可以通过以下方式重写 function 定义

void interChange(int *a, int *b)
{
    int tmp;
    tmp = a[0];
    a[0] = b[0];
    b[0] = tmp;
}

That is it looks like passing to the function arrays each of which contains only one element.也就是说,它看起来像传递给 function arrays 每个只包含一个元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM