2016-12-30 137 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; 
} 
相关问题