今天我用C ++编程时,我注意到了这种现象:
int main()
{
int a = 42;
func (a);
cout << a << endl;
}
void func (int x)
{
x = 5;
}
当然输出是42.否则要获得5作为输出我可以使用地址重写函数:
void func (int &x)
{
x = 5;
}
这是我的理解,但当我这样做时:
int main()
{
int a[2][2] = { {2,2}, {2,2} };
func (a);
cout << a[1][2] << endl;
}
void func (int x[2][2])
{
x[1][2] = 5;
}
输出实际上是5,但对我来说这是无法解释的。为什么func会影响main的任何变量?只是因为它是一个二维阵列?
答案 0 :(得分:3)
否则要获得5作为输出,我可以使用重写函数 地址:
void func (int &x) { x = 5; }
这里没有“地址”。 x
是一个参考。不要混淆引用和指针;他们是完全不同的东西。
void func (int x[2][2])
这是尝试将数组传递给函数。真正发生的是你传递一个指针。你传递的数组被称为“衰变”到指向数组第一个元素的指针(丢失所有大小的信息)。
就好像你用一个可爱的参数类型编写了你的函数:
void func(int (*x)[2])
{
x[1][2] = 5;
}
这里令人困惑的是你使用了二维数组。第二个维度的大小实际上保留在类型中。您可以再次将x[1]
传递给类似void func2(int y[2])
的函数,它会衰减为简单的int*
。
尽管如此,关键是你有不传递引用而是指针。指针本身按值传递 - 但指针用于间接修改main
中的数组。
请注意,可以通过引用传递数组。方法如下:
void func(int (&x)[2][2])
结论:
std::vector
/ std::array
代替原始数组。答案 1 :(得分:2)
首先是这个函数声明
void func (int x[2][2])
{
x[1][2] = 5;
}
相当于
void func (int x[][2])
{
x[1][2] = 5;
}
反过来相当于
void func (int ( *x )[2])
{
x[1][2] = 5;
}
该参数具有指向类型int[2]
的一维数组的指针类型。该函数获得了一个内存地址。
按以下方式调用该功能时
func (a);
数组a
被隐式转换为指向其第一个“行”(第一个元素)的指针。
因此该函数处理指针。它不会改变指针本身。 它改变了这个指针指向的内存。
在函数体表达式表达式
中x[1]
相当于*( a + 1 )
并产生数组a的第二个“行”(索引从0开始)。让它的名称为行
表达
x[1][2]
等同于row[2]
并产生对该行第三个元素的引用。
数组占用的内存中的值在函数中更改。也就是说,该函数不处理此单元格中的值的副本。它直接处理单元本身,因为我们提供了它的地址。
考虑到这个陈述
cout << a[1][2] << endl;
错了。数组a
的索引的有效范围声明为
int a[2][2]
是[0, 1]
。
所以你试图覆盖数组之外的内存。
答案 2 :(得分:0)
这称为 Decay
当作为参数传递时,数组衰减成原始指针。
编译器,decleration
void func (int x[2][2]);
与
相同void func (int* x[2]);
因此,数组作为指向第一个元素的指针发送,函数可以更改原始数组。