C++ 通过引用传递静态数组和动态数组
C++ Passing Static Array and Dynamic Array By Reference
为了完全理解指针、值和引用是如何工作的,我正在制作一个基本的 C++ 程序,它试图篡改一些静态和动态数组并准确理解它们应该如何传递。
首先我生成一个包含 3 个元素的静态数组。然后我将它传递给一个修改所有元素的函数。然后我将它传递给另一个函数,签名略有不同,但也可以改变数组的值。
接下来我生成一个动态大小的数组,通过引用将其传递给一个函数,这样这个动态大小的数组中的所有值都可以更改。
代码如下:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
以上所有代码都按我想要的方式工作,我只是有几个问题,为什么(我在其他 SO 问题上找到的一些通过引用传递数组的方法)。
在 changeIndexStaticArrayMethod1() 和 changeIndexDynamicArrayMethod1() 函数中,为什么我们可以对我们的数组使用取消引用 *
运算符作为引用?我的下意识反应是将其视为实际上按值传递数组,因为它是取消引用运算符。我知道对于数组,它与使用变量有很大不同,而且,为什么以下不适用于单个 int
变量:
void changeStaticNumber(int* num){
数 = 100;
}
显然,如果我们使用 &num
而不是 int* num
,上面的方法将起作用,显然我不完全理解指针和数组之间的关系,但我无法弄清楚为什么当我们通过引用数组,int* staticArray
没问题。
对于我遇到的这些问题的任何解释将不胜感激。谢谢。
让我看看我是否可以尝试一下。
指针只是地址持有者。一旦你做了 int * ptr = myarray; --- 你在 tern 做的是将指针 my 数组的地址存储到 ptr --- 数组名称实际上是指向数组中第一个内存位置的指针。您可以使用指针算法来获取其他所有内容,例如 myarray +1 将指向下一个位置或 myarray[1]。
当您需要修改数组时,按值传递不是很有用。通过引用传入本质上是指向数组并传递它。由于像向量这样的数组是连续的内存块,因此您可以很容易地对它们进行索引。
就您的示例而言 void changeStaticNumber(int* num){ num = 100;将不起作用,因为您试图做的是将 100 存储到指针的地址中。如果您引用 num 并使其无效 changeStaticNumber(int* num){ *num = 100;它将起作用,因为您实际上更进一步并访问了 num 指向的数据。当您使用 &num 时,它本质上是同一件事 - & 只是给您一些东西的地址。
例如,如果你想将一个指针指向一个 int,你会做的是
int num = 5;
int *ptr = #
此时 ptr 在 num 中具有相同的地址。要打印出 num 中的数据或 ptr 指向的数据,您需要取消引用或更进一步,因为我想告诉自己并取消引用 cout << *ptr;
在 changeIndexStaticArrayMethod1
和 changeIndexDynamicArrayMethod1
中,您没有传递数组,也没有通过引用传递(只有当参数类型是引用类型时才会发生——即 &
).参数的类型为 int *
(指向 int
的指针)。您正在按值 传递指向 int
的指针。两个函数都没有"dereference operator"。
ne
已经是一个int *
,所以通过它没什么特别的。 arr
是一个 int [3]
,一个数组,而不是一个指针。在 C 语言中,当在需要指向 T
的指针的上下文中使用数组 T
时,它会隐式转换(无需您做任何事情)指向其第一个指针元素。因此,当您这样做时,changeIndexStaticArrayMethod1(arr)
,编译器将获得指向 arr
的第一个元素的指针,并将其传递给函数。
[]
运算符作用于指针。 a[i]
始终保证与 *(a + i)
相同。在 changeIndexStaticArrayMethod1
和 changeIndexDynamicArrayMethod1
函数中,[]
用于使用指向第一个元素的指针访问后续元素。
why are we able to use the dereference * operator for our array as reference?
C 中的 *
有很多含义。它可以表示一元间接 ("contents of") 运算符,可以表示二进制乘法运算符,也可以表示指针声明。 int* stat
是一个指针声明。
由于您没有使用 *
取消引用该函数内指针的内容,我不太确定您在问什么。
当您在 main() 中获取数组的数组名称时,它 "decays" 成为指向第一个元素的指针。那么这些函数的作用是按值获取指针。如果您通过键入 *stat = something;
取消引用指针,您将访问 main.
中的实际数组
如果你做一些奇怪的事情,比如改变指针本身,例如stat++;
,那么它不会影响main中使用的地址。您按值传递了指针本身,因此指针是本地副本。
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
你不能在 C 或 C++ 中真正按值传递数组,除非诉诸肮脏的技巧(将它们存储在结构或 类 中)。例如,如果你的函数被写成 void changeIndexStaticArrayMethod1(int stat[3])
它仍然会给你一个指向第一个元素的指针。它不会按值传递数组,因为语法可能会让您相信。
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
因为num
是指针本身,而不是它的内容。为了编写这样的代码,您可以通过引用 int& num
传递变量。在背后,这实际上与传递指针是一回事,只是使用了简化的语法。
要更好地理解指针和数组之间的关系,请从阅读整章开始:http://c-faq.com/aryptr/index.html(C 和 C++ 在指针方面是相同的)。
为了完全理解指针、值和引用是如何工作的,我正在制作一个基本的 C++ 程序,它试图篡改一些静态和动态数组并准确理解它们应该如何传递。
首先我生成一个包含 3 个元素的静态数组。然后我将它传递给一个修改所有元素的函数。然后我将它传递给另一个函数,签名略有不同,但也可以改变数组的值。
接下来我生成一个动态大小的数组,通过引用将其传递给一个函数,这样这个动态大小的数组中的所有值都可以更改。
代码如下:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
以上所有代码都按我想要的方式工作,我只是有几个问题,为什么(我在其他 SO 问题上找到的一些通过引用传递数组的方法)。
在 changeIndexStaticArrayMethod1() 和 changeIndexDynamicArrayMethod1() 函数中,为什么我们可以对我们的数组使用取消引用
*
运算符作为引用?我的下意识反应是将其视为实际上按值传递数组,因为它是取消引用运算符。我知道对于数组,它与使用变量有很大不同,而且,为什么以下不适用于单个int
变量:void changeStaticNumber(int* num){ 数 = 100; }
显然,如果我们使用 &num
而不是 int* num
,上面的方法将起作用,显然我不完全理解指针和数组之间的关系,但我无法弄清楚为什么当我们通过引用数组,int* staticArray
没问题。
对于我遇到的这些问题的任何解释将不胜感激。谢谢。
让我看看我是否可以尝试一下。
指针只是地址持有者。一旦你做了 int * ptr = myarray; --- 你在 tern 做的是将指针 my 数组的地址存储到 ptr --- 数组名称实际上是指向数组中第一个内存位置的指针。您可以使用指针算法来获取其他所有内容,例如 myarray +1 将指向下一个位置或 myarray[1]。
当您需要修改数组时,按值传递不是很有用。通过引用传入本质上是指向数组并传递它。由于像向量这样的数组是连续的内存块,因此您可以很容易地对它们进行索引。
就您的示例而言 void changeStaticNumber(int* num){ num = 100;将不起作用,因为您试图做的是将 100 存储到指针的地址中。如果您引用 num 并使其无效 changeStaticNumber(int* num){ *num = 100;它将起作用,因为您实际上更进一步并访问了 num 指向的数据。当您使用 &num 时,它本质上是同一件事 - & 只是给您一些东西的地址。
例如,如果你想将一个指针指向一个 int,你会做的是
int num = 5;
int *ptr = #
此时 ptr 在 num 中具有相同的地址。要打印出 num 中的数据或 ptr 指向的数据,您需要取消引用或更进一步,因为我想告诉自己并取消引用 cout << *ptr;
在 changeIndexStaticArrayMethod1
和 changeIndexDynamicArrayMethod1
中,您没有传递数组,也没有通过引用传递(只有当参数类型是引用类型时才会发生——即 &
).参数的类型为 int *
(指向 int
的指针)。您正在按值 传递指向 int
的指针。两个函数都没有"dereference operator"。
ne
已经是一个int *
,所以通过它没什么特别的。 arr
是一个 int [3]
,一个数组,而不是一个指针。在 C 语言中,当在需要指向 T
的指针的上下文中使用数组 T
时,它会隐式转换(无需您做任何事情)指向其第一个指针元素。因此,当您这样做时,changeIndexStaticArrayMethod1(arr)
,编译器将获得指向 arr
的第一个元素的指针,并将其传递给函数。
[]
运算符作用于指针。 a[i]
始终保证与 *(a + i)
相同。在 changeIndexStaticArrayMethod1
和 changeIndexDynamicArrayMethod1
函数中,[]
用于使用指向第一个元素的指针访问后续元素。
why are we able to use the dereference * operator for our array as reference?
C 中的 *
有很多含义。它可以表示一元间接 ("contents of") 运算符,可以表示二进制乘法运算符,也可以表示指针声明。 int* stat
是一个指针声明。
由于您没有使用 *
取消引用该函数内指针的内容,我不太确定您在问什么。
当您在 main() 中获取数组的数组名称时,它 "decays" 成为指向第一个元素的指针。那么这些函数的作用是按值获取指针。如果您通过键入 *stat = something;
取消引用指针,您将访问 main.
如果你做一些奇怪的事情,比如改变指针本身,例如stat++;
,那么它不会影响main中使用的地址。您按值传递了指针本身,因此指针是本地副本。
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
你不能在 C 或 C++ 中真正按值传递数组,除非诉诸肮脏的技巧(将它们存储在结构或 类 中)。例如,如果你的函数被写成 void changeIndexStaticArrayMethod1(int stat[3])
它仍然会给你一个指向第一个元素的指针。它不会按值传递数组,因为语法可能会让您相信。
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
因为num
是指针本身,而不是它的内容。为了编写这样的代码,您可以通过引用 int& num
传递变量。在背后,这实际上与传递指针是一回事,只是使用了简化的语法。
要更好地理解指针和数组之间的关系,请从阅读整章开始:http://c-faq.com/aryptr/index.html(C 和 C++ 在指针方面是相同的)。