问题 从函数中改变数组元素的值


我是C ++的新手(每个新手XD的常用介绍)。好吧,当一个出乎意料的行为出现时,我正在开发一个程序! 我在程序中跟踪变量和数组,直到我成功确定执行此行为的代码模式!

以下是我用来追踪事情如何运作的内容:

#include <iostream>

using namespace std;

void showArray(int arr[], int n)
{
    for(int i = 0; i < n; i++) cout << arr[i] << " ";
    cout << endl;
}
void someFunction(int x[], int n) // changes the original values
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
} 
void someFunction2(int * x, int n)
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
} // changes the original values
int someFunction3(int x[], int n)
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
    return 0;
} // changes the original values
int someFunction4(int x[], int n)
{
    x = new int[n];
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
    return 0;
} // does NOT change the original value

int main(void)
{
    int * y = new int[3];
    y[0] = 0;
    y[1] = 1;
    y[2] = 2;
    showArray(y, 3);
    someFunction4(y, 3);
    showArray(y, 3);
    return 0;
}

我认为带有注释的代码解释了问题所在,但是这里有更多信息: 有4个函数,分别是someFunction,someFunction2,someFunction3,someFunction4。 有一个数组y,其值为0,1,2。 所有函数都会更改原始数组的值。也就是说,someFunctionX调用之后main函数中的y元素比调用函数之前的元素更改。

我的问题是:为什么someFunction4是唯一不改变值的函数?

提前致谢。抱歉我的英语不好


2136
2017-11-08 18:03


起源



答案:


someFunction4,你指定 x 指向一个 new 然后分配的整数数组。传递给函数的变量指向的数组仍然指向旧数组。旧数组保持不变,因为在内部 someFunction4 你已经设定好了 x 引用不同的数组,即您在函数中创建的数组 new

为了制作原创 x 在 someFunction4() 保持您指定的值,执行以下两项操作之一:

1)摆脱 x = new int[n];。这将使 someFunction4() 像以前那样工作。

2)将指针传递给 x 作为一个论据 someFunction4() 并有 someFunction4() 拿一个指针。

int someFunction4(int *x[], int n)
{
    *x = new int[n];
    (*x)[0] = 2;
    (*x)[1] = 1;
    (*x)[2] = 0;
    return 0;
} // Makes x point to a new a new array

在你的主要,做

someFunction4(&y,3); 

7
2017-11-08 18:10



谢谢。你的答案很明确。那么,如何使旧数组获取新值? - joker
摆脱任务 x = new int[n]; - GraphicsMuncher
如果我想从函数中改变数组大小怎么办? - joker
有 someFunction4 获取指向int数组而不是int数组的指针,然后在函数中取消引用它。那会改变它。 - GraphicsMuncher
啊,是的,它现在有效,并做你想要的。我编译了它。运算符优先级, 叹。 - GraphicsMuncher


答案:


someFunction4,你指定 x 指向一个 new 然后分配的整数数组。传递给函数的变量指向的数组仍然指向旧数组。旧数组保持不变,因为在内部 someFunction4 你已经设定好了 x 引用不同的数组,即您在函数中创建的数组 new

为了制作原创 x 在 someFunction4() 保持您指定的值,执行以下两项操作之一:

1)摆脱 x = new int[n];。这将使 someFunction4() 像以前那样工作。

2)将指针传递给 x 作为一个论据 someFunction4() 并有 someFunction4() 拿一个指针。

int someFunction4(int *x[], int n)
{
    *x = new int[n];
    (*x)[0] = 2;
    (*x)[1] = 1;
    (*x)[2] = 0;
    return 0;
} // Makes x point to a new a new array

在你的主要,做

someFunction4(&y,3); 

7
2017-11-08 18:10



谢谢。你的答案很明确。那么,如何使旧数组获取新值? - joker
摆脱任务 x = new int[n]; - GraphicsMuncher
如果我想从函数中改变数组大小怎么办? - joker
有 someFunction4 获取指向int数组而不是int数组的指针,然后在函数中取消引用它。那会改变它。 - GraphicsMuncher
啊,是的,它现在有效,并做你想要的。我编译了它。运算符优先级, 叹。 - GraphicsMuncher


在每一个 someFunctionsomeFunction2,和 someFunction3,你实际上正在通过 指针 到您为阵列分配的内存中 main()。这意味着当您对数据进行操作时,此指针指向:

x[1] = 1;

它实际上影响了相同的内存 y 指向回来 main()

但是,在 someFunction4,你 重新分配 指针 x 用语句指向新内存:

x = new int[n];

所以它不再指向同样的记忆 y 做的 main(),以及之后您所做的任何更改(但仅限于范围内) someFunction4!)不会影响 y


5
2017-11-08 18:13





我做了一个测试用例。

http://ideone.com/fyl6MX

结果

0 1 2 
0x943b008
0x943b018
0x943b008
0 1 2 

第二个是地址是新表的地址。如您所见,您的指针在本地指向其他地址。

#include <iostream>

using namespace std;

void showArray(int arr[], int n)
{
    for(int i = 0; i < n; i++) cout << arr[i] << " ";
    cout << endl;
}
void someFunction(int x[], int n) // changes the original values
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
} 
void someFunction2(int * x, int n)
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
} // changes the original values
int someFunction3(int x[], int n)
{
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
    return 0;
} // changes the original values
int someFunction4(int x[], int n)
{
    x = new int[n];
    std::cout << x << endl;
    x[0] = 2;
    x[1] = 1;
    x[2] = 0;
    return 0;
} // does NOT change the original value

int main(void)
{
    int * y = new int[3];
    y[0] = 0;
    y[1] = 1;
    y[2] = 2;
    showArray(y, 3);

    std::cout << y  << endl;

    someFunction4(y, 3) ;
    std::cout << y << endl;

    showArray(y, 3);
    return 0;
}

2
2017-11-08 18:12



那么如何从函数中改变原始指向值呢? - joker


您必须了解如何将参数传递给函数

当你调用SomeFunctionN(y,3)然后在SomeFunctionN里面,'x'变量是一个局部变量,被初始化为指向y指向main的同一个数组。

然后在SomeFunc4中创建一个新数组并将本地指针(x)更改为指向新数组。您所做的所有更改都会触及新阵列

在所有其他情况下,你只留下x


0
2017-11-08 18:10