C ++需要解释这个功能

时间:2015-11-03 16:24:51

标签: c++ arrays function multidimensional-array

今天我用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的任何变量?只是因为它是一个二维阵列?

3 个答案:

答案 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]);

因此,数组作为指向第一个元素的指针发送,函数可以更改原始数组。