1

基本的に私がやろうとしているのは、関数内で配列を初期化することですが、セグメンテーション違反になります:

void func(int **a, int x, int y) {
    a = new int*[x];

    for (int i=0; i<x; i++)
        a[i] = new int[y];
}

void main() {
    int **a;    
    func(a, 2, 3);
}

ただし、関数の外側で配列を初期化して渡すと、すべてが完全に機能し、値を割り当てたり出力したりできます。私が苦労しているのは、配列の参照を渡すことなので、関数の外で初期化する必要はありません。

void func(int **a, int x, int y) {  
    for (int i=0; i<x; i++)
        a[i] = new int[y];
}

void main() {
    int x = 2;
    int **a = new int*[x];  
    func(a, x, 3);
}
4

3 に答える 3

4

ここであなたを悩ませているのは、C (および C++) には参照による引数の受け渡しがないことです。ainはinmain()とは異なります。afunc()

  1. aで宣言されていmainます。
  2. a値によって (他に方法がないため) に渡されますfunc
  3. に割り当てられますafunc
  4. func戻り値。それaは破壊され(メモリリーク)、は初期化されていないままmainですa
  5. ???
  6. mainを使用してみますaセグメンテーション!

ここで考えられる解決策がいくつかあります。

  1. 古典的な C の方法で行います: 値へのポインターを渡します。この場合、パラメータは になりますがint ***a、これは少しばかげていますが、何でも構いません。

    void func(int ***a, int x, int y) {  
        *a = new int*[x];
        for (int i=0; i<x; i++)
            (*a)[i] = new int[y];
    }
    
    int main(int argc, char **argv) {
        ...
        int **a;
        func(&a, 2, 3);
        ...
    }
    
  2. C++ の方法で行います: 参照を渡します。

    void func(int **&a, int x, int y) {
        //          ^
        // This is the only change. Neat!
    
  3. (私の意見では)適切な方法で実行します。関数から値を返し、それから配列を初期化します。

    int **func(int x, int y) {
        int **a = new int*[x]; // EDIT: Fixed stupid typo bug
        // existing code
        return a;
    }
    
    int main(int argc, char **argv) {
        ...
        int **a = func(2, 3);
        ...
    }
    
于 2013-07-21T23:53:30.517 に答える
1

元のコードが行うことは、main のローカル変数ではなく、func のローカル変数を変更することです。これはあなたが望むことをします:

void func(int **&a, int x, int y) {
    a = new int*[x];

    for (int i=0; i<x; i++)
            a[i] = new int[y];
}

void main() {
    int **a;    
    func(a, 2, 3);
}

そうしないと、func を呼び出した後にメインの配列にアクセスしようとしない限り、セグ フォールトが発生する理由がわかりません。

于 2013-07-21T23:51:29.087 に答える