2016-12-30 147 views
0

這聽起來有點奇怪,我只是說因爲我不知道我怎麼能說出來。我試圖實現A *,之前我做過,但是我有一個跟蹤我的路徑的問題,所以我決定運行一個小測試。這個問題又是這樣的:爲什麼我不能擁有指向與成員變量指針類型相同的對象的指針?

我有一個類,看起來有點像這樣:

class Number { 
public: 
    int xPos; 
    int yPos; 

    Number *prevNum; 
    Number(int x, int y) { 
     xPos = x; 
     yPos = y; 
    } 
}; 

,並在主函數中,我這樣做

int main() { 
    Number n(2, 2); 
    Number *current = &n; 
    vector<Number> nums; 
    nums.push_back(*current); 
    for (unsigned i = 0; i < 15; i++) { 
     Number n(current->xPos + 1, current->yPos); 
     n.prevNum = current; 
     nums.push_back(n); 
     current = &n; 
     cout << current->xPos + 1 << " "; 
    } 
    for (unsigned i = 0; i < nums.size(); i++) { 
     if (nums.at(i).prevNum) { 
      cout << nums.at(i).prevNum->xPos << " "; 
     } 
    } 
    return 0; 
} 

出於某種原因,返回這個:

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 555437610 2 17 17 17 17 17 17 17 17 17 17 17 17 17 17 

555437610每次都不一樣,所以我假設我可能會有一個錯誤wi th指針。我不能無限嵌套成員函數* prevNum嗎?我不完全確定如何描述它。

+3

不是太挑剔,但你確定這個類代表一個_Number_?重命名可能有意義。 – byxor

+4

您的構造函數確實應該將'prevNum'設置爲'nullptr'。 –

+0

'n'是for循環中的一個局部變量,所以'&n'在循環外部都是未定義的。 –

回答

3

你的問題是與

current = &n; 

在這裏,你正在服用的循環局部變量的地址。在迭代結束時,變量被銷燬,這意味着你有一個指向不再存在的對象的指針。取消引用該指針是未定義的行爲。

如果你想保持定義的行爲,你應該做的是存儲一個指向矢量中的對象的指針。在撥打push_back之後,該指針可能會失效,但由於您在此之前使用它,所以它會沒事的。你應該沒問題

current = &nums.back(); 

你也將有一個問題存儲以前的指針。如果你從矢量中捕獲元素,如果矢量重新分配空間,那麼你將留下一個懸掛指針。我想你將需要某種shared_ptr設置爲了得到這個工作。

1

n的範圍僅爲for循環。因此current = &n;設置current指向一個即將超出範圍的對象。

nums.push_back(n);n複製到向量中,並且它是&nums.back()您應該將其分配給current

事實上,你的程序可以簡化如下:

struct Number { // Now a proper aggregate 
    int xPos; 
    int yPos; 

    Number *prevNum; 
}; 

vector<Number> nums {{1, 2, nullptr}}; 
nums.reserve(16); 
for (unsigned i = 0; i < 15; ++i) { 
    Number& back = nums.back(); 
    nums.emplace_back({back.xPos + 1, back.yPos + 1, &back}); 
    cout << nums.back().xPos + 1 << " "; 
} 
+0

這仍然有UB。一旦矢量重新分配,存儲'&back'將不起作用。 – NathanOliver

+0

@NathanOliver - 所以我只提前預留空間。 – StoryTeller

+0

這將工作。 – NathanOliver

2

您有:

for (unsigned i = 0; i < 15; i++) { 
    Number n(current->xPos + 1, current->yPos); 
    n.prevNum = current; 
    nums.push_back(n); 
    current = &n; 
    cout << current->xPos + 1 << " "; 
} 

有,n是當循環結束是被破壞的局部變量。您正在存儲一個指向本地變量的指針,並在稍後使用它。

您的程序有未定義的行爲。


我不清楚爲什麼你需要prevNum成員變量。 你可以完全擺脫它。

#include <iostream> 
#include <vector> 

using namespace std; 

class Number { 
public: 
    int xPos; 
    int yPos; 

    Number(int x, int y) { 
     xPos = x; 
     yPos = y; 
    } 
}; 

int main() { 
    Number n(2, 2); 
    vector<Number> nums; 
    nums.push_back(n); 
    for (unsigned i = 0; i < 15; i++) { 
     Number n(2+i+1, 2); 
     nums.push_back(n); 
     cout << 2 + i+1 << " "; 
    } 
    cout << endl; 
    for (unsigned i = 0; i < nums.size(); i++) { 
     cout << nums.at(i).xPos << " "; 
    } 
    cout << endl; 
    return 0; 
} 
相關問題