1
    void nothing(int* buffer)
    {
        int* temp = new int[5];
        for (int i = 0; i < 5; i++)
        {
            temp[i] = i;
        }
        buffer = temp;
    }

    void main(int argc, char* argv[])
    {
        int* a = new int;
        nothing(a);
        for (int i = 0; i < 5; i++)
        {
            cout << a[i] << endl;
        }
        system("pause");
    }

バッファから新しいアドレスを取得できないのはなぜですか? 配列(ポインター)を関数に渡して内部で変更しようとしています。

出力:

 -842150451
-33686019
-1414812757
-1414812757
0

期待される:

0
1
2
3
4
4

6 に答える 6

3

ポインターをポインターに渡す必要があります(または、他の人がポインターへの参照を指摘したように)。つまりint **、を使用して割り当て*buffer = temp、関数を使用して呼び出しますnothing(&a)

これを行わないと、関数を終了したときにバッファ変数に加えた変更が失われます。ポインター変数自体は、関数が終了した後もそれが指し示すものとして存続する任意の数値と同様に考えてください。

ただし、代わりに std::vector を使用することをお勧めします。

void nothing(std::vector<int> &buffer) {
    ...
}

int main(int argc, char* argv[])
{
    std::vector<int> a;
    nothing(a);
    for (int i = 0; i < 5; i++)
    {
        cout << a[i] << endl;
    }
    system("pause");
    return 0;
}

シナリオによっては、nothing 関数を初期化スタイルの関数に変更したい場合もあります。つまり、オブジェクトを直接返します。

std::vector<int> nothing() {
    std::vector<int> temp;
    // fill vector here
    return temp;
}

int main(int argc, char* argv[])
{
    auto a = nothing();
    for (int i = 0; i < 5; i++)
    {
        cout << a[i] << endl;
    }
    system("pause");
    return 0;
}

これははるかに C++ 風であり、配列を手動で削除する必要がなくなります。

実際にデータをベクトルに生成するには、Initialization of std::vector<unsigned int> with a list of continuous unsigned integers をご覧 ください。

于 2013-11-01T20:47:56.167 に答える
1

重要な前置き:vector可能であれば、配列/ポインターの代わりに使用してください。私たちは皆、これを可能な限り奨励します!何か非常に複雑なソフトウェアを書いて、何か月も続けてプログラミングすることは十分に可能であり、それらの厄介な C の問題を呼び出す必要も、心配する必要もありませんnewdelete


使用をやめてtempください!

void nothing(int* buffer)
{
    for (int i = 0; i < 5; i++)
    {
        buffer[i] = i;
    }
}

これは、配列へのポインタを入力として受け取ります。そして、その配列に直接書き込みます。

前のコードで 2 番目の配列が作成されました。呼び出すnewたびに、新しい配列を取得します。int* temp = new int[5];. このアプローチを機能させるには、temp 配列のデータを buffer 配列にコピーする必要があります。ただし、C では (簡単に) 配列をコピーすることはできません。

buffer = temp;  // This *doesn't* copy any array

この行は何もしませんでした。2 つの配列はまだ存在しており、その結果、データはコピーされませんでした。呼び出されたローカル変数bufferはここで変更されました。しかし、変更はわずかでした。バッファは古い配列を指していましたが、現在は新しい配列を指しています。また、buffer はローカル変数であるため、関数が戻るとすぐにすべての意味を失います (非ローカル データを指しbufferていましたが、ポインター自体はまだローカルです。

要するに、元のnothing関数は何の役にも立ちませんでした。新しい配列を作成し、それにいくつかの値を入れてから、それを無視しました。内部のバッファ変数mainは、関数の影響を受けませんでした。

于 2013-11-01T21:12:02.043 に答える
0

ポインターbufferは値渡しされており (これは C++ のデフォルトです)、これはコピーが作成されることを意味します。次に、このコピーを変更します。これは C++ であるため、代わりに参照を渡すことができます。

void nothing(int*& buffer)

このようにして、コピーではなく元のオブジェクトが渡されます。

于 2013-11-01T20:55:16.883 に答える
0

「配列(ポインタ)を関数に渡して内部で変更しようとしています」

しかし、コードが行うことは、 1 のメモリを割り当て、intこのメモリへのポインターを関数に渡し、関数が配列を割り当て、アドレスまたはこの新しく割り当てられた配列を渡されたポインターに割り当てようとすることです。つまり、変更しようとします。ポインター自体

int**代わりに渡すようにint*して、呼び出し元に任せます。

int* a;
nothing(&a);

また、C++ では、関数がいくつかのリソースを動的に割り当て、これらのリソースを解放する責任の形で (この場合は を呼び出す特定の手段を使用してもdelete[]) 呼び出し元に負担をかけるという一般的な慣行よりもむしろまれであることに注意してください。またはなどの STL コンテナーの使用を検討してくださいstd::vector。C スタイルの配列に固執する必要がある場合は、少なくとも自動保存期間を備えたものを優先してください。

于 2013-11-01T20:49:36.953 に答える
0

tempNothing() 内で宣言されたローカル変数です。これは、Nothing() が戻ると、temp のメモリが失われることを意味します。ローカル変数内からデータを取り戻すことはできません-したがって、ゴミです。

于 2013-11-01T20:50:31.647 に答える
0

a は値によって何も渡されないため、そのコピーを何も変更しても a には影響しません。参照渡しの場合は渡すか、@villintehaspam が言うように、ポインターをポインターに渡す必要があります。

于 2013-11-01T20:48:41.580 に答える