2016-12-04 43 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, (在時間迭代中)這個數組的2個變體在int指針列表中。

因此,在第一次迭代中,2個數組{2,3,4,5,6,7,8,9,1}和{0,2,3, ,5,6,7,-1 }應存放在列表中,因此,第3 printArray應該是:

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 printArray是:

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 

我已經已經印刷taTB在每次迭代和我知道真的被打印出的是1)默認數組,2)第一TA,3)第一TA的TB。但我真的不知道這種行爲的原因是什麼,我的意思是,在每次迭代中,新陣列(獨立於以前的陣列)不是tatb?如果是這種情況,我的for只是爲新陣列位置分配值,那麼爲什麼它們會相互衝突呢?

+1

注意,ta和tb陣列存儲器AINT由STD矢量管理。我的猜測是,在連續的迭代中,數組可能會被釋放並且行爲不確定。嘗試在while循環之外分配它們 – quimnuss

+0

也沒有三個int指針數組,您有三個指向各自int數組的指針。 – quimnuss

+0

它是有道理的如果這就是原因。是的,如果我以前在while循環之外分配了所需數組的數量,或者只是在每次迭代時只是'int * ta = new int [9] ...',它基本上都是相同的。我的猜測是,由於ta和tb是while循環的局部變量,它們只會在範圍的末尾有效,這就是迭代本身的結束......您同意嗎? @quimnuss – yat0

回答

0

問題其實很簡單。

正如評論指出@quimnuss,TATB在某一點重新分配,因此,保存在列表中的指針將指向東西從那些被釋放,數組完全不同的,導致和未定義程序的行爲。

這種說法使得完整的意義,因爲TATB是while循環的局部變量,因此其有效性將在每次迭代完成用完。

我們可以解決這個問題,通過在每次迭代動態分配內存,如:

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

這遠沒有信息丟失在每次迭代之後將發生的,因爲這個陣列的範圍不再是本地的while循環。

最終代碼:

#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

你在這裏玩火。 'array'的第一個元素是'v',它被分配了堆棧。其餘的都是動態分配的,所以需要'刪除'd。你確定你不能只使用std :: vector 或std :: array ?這會讓內存管理變得更容易 –

+0

是的,我做到了。這只是我的一個朋友試圖做的一個方法,在一個問題的背景下,我對它很感興趣,只是在這裏問到爲什麼它沒有工作。我將更新代碼,在使用它之後立即刪除內存。 @JosephIreland – yat0

+0

所以,這是正確的,雖然非常非常醜陋。我同意約瑟夫你正在玩火。儘管如此,由於您創建了「times * 2 + 1」堆分配矢量,並且只刪除了「times」,所以您的內存泄漏很大。我堅持認爲,將分配和刪除移出循環,否則你會混合範圍,儘管它會工作,因爲它的堆分配,這是很難閱讀。請注意,分配可以保持原樣。除了內存泄漏你還有。 – quimnuss