16

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

someFunction4()で配列yを変更しないのはなぜmain()ですか? 代わりにもう一方someFunctionX()を呼び出すと、から に正常に変更されます。main()y{0, 1, 2}{2, 1, 0}

4

4 に答える 4

10

では、整数の配列を指すようにsomeFunction4代入し、それを代入します。関数に渡した変数が指す配列は、まだ古い配列を指しています。内部で別の配列、つまり を介して関数で作成した配列を参照するように設定しているため、古い配列は変更されません。xnewsomeFunction4xnew

x割り当てた値を保持するオリジナルを作成するには、次someFunction4()の 2 つのいずれかを行います。

1) を取り除きx = new int[n];ます。これによりsomeFunction4()、以前のものと同じように機能します。

x2) への引数としてポインタを渡し、ポインタを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); 
于 2012-11-08T18:10:35.540 に答える
5

、、およびのそれぞれでsomeFunction、実際にはで配列に割り当てたメモリへのポインタを渡しています。これは、データを操作するときに、このポインターが指す次のことを意味します。someFunction2someFunction3main()

x[1] = 1;

実際には、yback を指すのと同じメモリに影響しmain()ます !

ただし、 ではsomeFunction4、ステートメントを使用してポインタを新しいメモリを指すように再割り当てします。x

x = new int[n];

yそのため、 で行うのと同じメモリを指しなくなり、main()その後に変更を加えても (! の範囲内でのみsomeFunction4) 影響を受けませんy

于 2012-11-08T18:13:53.637 に答える
2

テストケースを作りました。

http://ideone.com/fyl6MX

結果

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

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;
}
于 2012-11-08T18:12:20.890 に答える
0

引数が関数に渡される方法を理解する必要があります

SomeFunctionN(y,3) を呼び出すと、SomeFunctionN 内で 'x' 変数は、メインで y が指していたのと同じ配列を指すように初期化されたローカル変数になります。

SomeFunc4 では、新しい配列を作成し、ローカル ポインター (x) を新しい配列を指すように変更します。あなたが行ったすべての変更は、新しい配列にヒットします

それ以外の場合はすべて x をそのままにしておきます

于 2012-11-08T18:10:37.740 に答える