Изменение значений элементов массива из функции

Я новичок в С++ (обычный ввод для каждого новичка 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. все функции меняют значение исходного массива. То есть, элементы y в основной функции после вызова someFunctionX меняются, чем они были до вызова функции.

мой вопрос: почему someFunction4 является единственной функцией, которая не меняет значения?

Заранее спасибо. и извините за мой плохой английский.

Ответ 1

В 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); 

Ответ 2

В каждом из someFunction, someFunction2 и someFunction3 вы фактически передаете pointer в память, которую вы выделен для вашего массива в main(). Это означает, что когда вы работаете с данными, этот указатель указывает на:

x[1] = 1;

Фактически это влияет на ту же память, что y указывает назад в main()!

Однако в someFunction4 вы переназначите указатель x, чтобы указать на новую память с помощью инструкции:

x = new int[n];

Поэтому он больше не указывает на ту же память, что y делает в main(), и любые изменения, которые вы вносите в нее после этого (но только в пределах области someFunction4!), не будут влиять на y.

Ответ 3

Я сделал тестовый файл.

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;
}

Ответ 4

Вам нужно понять, как аргументы передаются функциям

Когда вы вызываете SomeFunctionN (y, 3), то внутри SomeFunctionN переменная 'x' является локальной переменной, инициализированной для того, чтобы указывать на тот же массив, что y указывал в main.

в SomeFunc4 вы создаете новый массив и меняете локальный указатель (x), чтобы указать на новый массив. Все сделанные вами изменения попадают в новый массив

Во всех остальных случаях вы оставляете x в покое