2016-12-04 13 views
-1

たぶん私はちょうど混乱物事少しだ..しかし、C++のコードのこの部分を検討してください:あなたが見ることができるようにこのポインタが競合する理由は何ですか?

#include <iostream> 
#include <list> 
using namespace std; 

void printArray(int *arr, int n) 
{ 
    for(int i=0; i<n; ++i) 
    cout << arr[i] << " "; 

    cout << endl; 
} 

int main() 
{ 
    list<int*> arrays; 
    int times=20, v[9]={1,2,3,4,5,6,7,8,0}; 

    arrays.push_back(v); 

    while(times--) 
    { 
     int *cur = arrays.front(); 
     arrays.pop_front(); 

     printArray(cur, 9); 

     int ta[9], tb[9]; 
     for(int i=0; i<9; ++i) 
     { 
      ta[i] = *(cur+i)+1; 
      tb[i] = *(cur+i)-1; 
     } 

     arrays.push_back(&ta[0]); 
     arrays.push_back(&tb[0]); 
    } 

    return 0; 
} 

を、客観的にはデフォルトの配列{1,2、とbegginingにあります3,4,5,6,7,8,0}、store(in times iterations)intポインタのリストにあるこの配列の2つの変種。

したがって、最初の反復では、2つの配列{2,3,4,5,6,7,8,9,1}と{0,2,3, ,5,6,7、-1私はしました

1 2 3 4 5 6 7 8 0 
2 3 4 5 6 7 8 9 1 
2 3 4 5 6 7 8 9 1 

:最初の3 プリントアレイであるということです

1 2 3 4 5 6 7 8 0 
2 3 4 5 6 7 8 9 1 
0 1 2 3 4 5 6 7 -1 

、起こっていただきました!:}リストに保存する必要があるので、最初の3 プリントアレイはする必要があります既に印刷されたta各反復における結核と私は本当に、プリントアウトされているもの1)デフォルトの配列、2)最初のta、最初のTAの3) TBであることを知っています。しかし、私は実際にこの動作の理由がわからない、つまり、各反復で新しい配列(以前のものとは独立しています)がtatbではありませんか?これが当てはまる場合、私のforは新しい配列の位置の値を割り当てているだけなので、なぜそれらは互いに衝突していますか?

+1

注意。私の推測では、連続した繰り返しでは、配列の割り当てを解除することができ、動作は未定義です。 whileループの外側にそれらを割り当ててみてください – quimnuss

+0

また、3つのintポインターの配列を持たず、それぞれのint配列に3つのポインターがあります。 – quimnuss

+0

それが理にかなっていれば意味があります。そして、私が以前にwhileループの外側に必要な配列の量を割り当てるか、単純にすべての反復で 'int * ta = new int [9] ... 'とすれば、それはうまく動作します。私の推測は、taとtbはwhileループのローカル変数であるため、スコープの終わりまで有効であり、それは反復自体の終わりです。同意しますか? @quimnuss – yat0

答えて

0

問題は実際には非常に簡単です。

コメントで述べたよう@quimnuss、 TAとTB は、いくつかの時点で割り当て解除されたので、リストに保存されたポインタがにつながる、割り当てが解除されたこれらの配列とは全く違うものを指しますと、未定義プログラムの動作。

この文は、 TAとTB ので、完全な理にかなっているwhileループのローカル変数ですので、その有効性は、各反復の終了時に出て実行されます。

我々は次のように、動的に各繰り返しでメモリを割り当てることで、この問題を回避することができます。この配列の範囲は、もはやに対してローカルであるため、情報の損失は、全ての反復終わりに起こりません

int *ta = new int[9]; 
int *tb = new int[9]; 

この距離whileループ。

決勝コード:TAとTBアレイメモリAINTはSTDベクトルが管理していること

#include <iostream> 
#include <list> 
using namespace std; 

void printArray(int *arr, int n) 
{ 
    for(int i=0; i<n; ++i) 
    cout << arr[i] << " "; 

    cout << endl; 
} 


int main() 
{ 
    list<int*> arrays; 
    int times=20;  

    int *v = new int[9]; 
    for(int i=0; i<8; ++i) 
     v[i] = i+1; 
    v[8] = 0; 

    arrays.push_back(v); 

    while(times--) 
    { 
     int *cur = arrays.front(); 
     arrays.pop_front(); 

     printArray(cur, 9); 

     int *ta = new int[9]; 
     int *tb = new int[9]; 

     for(int i=0; i<9; ++i) 
     { 
      ta[i] = *(cur+i)+1; 
      tb[i] = *(cur+i)-1; 
     } 

     arrays.push_back(ta); 
     arrays.push_back(tb); 

     delete[] cur; 
    } 

    while(!arrays.empty()) 
    { 
     int *p = arrays.front(); 
     arrays.pop_front(); 
     delete[] p; 
    } 

    return 0; 
} 
+2

あなたはここで火事をしています。 'arrays'の最初の要素は' v'で、スタックに割り当てられます。残りは動的に割り当てられるので、 'delete'dする必要があります。 std :: vector またはstd :: array を使うことはできませんか?それはメモリ管理をはるかに容易にするだろう –

+0

はい、私はそれを行った..これは私の友人が問題の文脈でしようとしていた方法だった、と私はそれに興味を持って、機能していませんでした。私はコードを更新します、私はそれを使用した直後にメモリを削除しています。 @JosephIreland – yat0

+0

これは正しいですが、非常に、非常に醜いです。私はあなたが火で遊んでいるジョセフと同意する。それにもかかわらず、 'times * 2 + 1'ヒープ割り当てベクトルを作成し、' times'だけを削除するので、大きなメモリリークが発生します。私は主張して、割り当てや削除をループから外してください。さもなければ、スコープを混在させていて、ヒープ割り当てされているので読み込みが難しいです。割り当てはそのままで留まることに注意してください。メモリリークに加えて、あなたはまだ持っています。 – quimnuss

関連する問題