C++ 需要解释此功能

C++ Need explaination for this functions

本文关键字:功能 解释 C++      更新时间:2023-10-16

当我今天在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 会影响主变量的任何变量?仅仅因为它是 2D 阵列?

否则,要获得 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 而不是原始数组。

首先这个函数声明

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].

因此,您正在尝试覆盖阵列之外的内存。

称为衰变
数组在作为参数传递时衰减为原始指针。

对于编译器,降级

void func (int x[2][2]); 

void func (int* x[2]);

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