2009-07-06 69 views
3

我有一個名爲頂點結構,我創造了一些指向他們。我想要做的是將這些指針添加到列表中。我的代碼如下,當它試圖將指針插入到列表中時,會創建一個分段錯誤。有人可以解釋發生了什麼嗎?STL列表持有結構指針

#include <iostream> 
#include <list> 

#define NUM_VERTICES 8 

using namespace std; 

enum { WHITE, GRAY, BLACK }; 

struct vertex 
{ 
    int color; 
    int distance; 
    char parent; 
}; 

int main() 
{ 
    //create the vertices 
    vertex r = {WHITE, NULL, NULL}; 

    //create pointer to the vertex structures 
    vertex *pr = &r; 

    //create a list to hold the vertices 
    list<vertex*> *r_list = new list<vertex*>; 

    list<vertex*>::iterator it; 

    r_list->insert(it, pr); 
} 
+0

你在主函數中缺少返回值 – rfcoder89 2016-10-01 07:48:51

回答

10

有這裏有幾個錯誤。

首先,你是不是初始化迭代器,像其他的說:

list<vertex*>::iterator it = r_list->begin(); 

做到這一點,你的代碼將被罰款。但是你的代碼是以不好的方式完成的。

你爲什麼要從堆中分配列表?看看你的代碼:你有內存泄漏。你不在任何地方撥打delete r_list。這就是爲什麼你應該使用智能指針(std::unique_ptrstd::shared_ptr如果你有C++ 11,升壓等效否則:boost::scoped_ptrboost::shared_ptr

但更好的是,只是做了堆棧上:

//create a list to hold the vertices 
list<vertex*> r_list; 

list<vertex*>::iterator it = r_list->begin(); 

r_list.insert(it, pr); 

另外,使用迭代器插入正在經歷漫長的過程。只要使用push front()push back()

//create a list to hold the vertices 
list<vertex*> r_list; 

r_list.push_back(pr); 

另一件事:如果你的列表會超越你已經構建了頂點,這將指向東西無效。

例如:

// global 
list<vertex*> r_list; 

void some_function(void) 
{ 
    //create the vertices 
    vertex r = {WHITE, NULL, NULL}; 

    //create pointer to the vertex structures 
    vertex *pr = &r; 

    r_list.push_back(pr); 
} // right here, vertex r stops existing: the list now contains an 
    // invalid pointer. 

一個解決方案是存儲指向堆分配的頂點:

// global 
list<vertex*> r_list; 

void some_function(void) 
{ 
    //create the vertices 
    vertex *r = new vertex; 
    r->color = WHITE; 
    r->distance = 0; 
    r->parent = 0; 

    r_list.push_back(r); 
} 

即使列表被指向有效的堆分配頂點後的功能現在。現在有一個問題,即當您完成使用列表時,您需要通過lsit並在每個元素上調用delete。這個問題是通過使用Boost Pointer Container Library來協助的。

的最好辦法,雖然是隻存放頂點本身(而不是指向它們的指針):

//create a list to hold the vertices 
list<vertex> r_list; 

//create the vertices 
vertex r = {WHITE, NULL, NULL}; 

r_list.push_back(r); 

如果給頂點構造函數,你甚至可以只構建他們就地:

struct vertex 
{ 
    int color; 
    int distance; 
    char parent; 

    vertex(int _color, int _distance, char _parent) : 
    color(_color), 
    distance(_distance), 
    parent(_parent) 
    { 
    } 
}; 

//create a list to hold the vertices 
list<vertex> r_list; 

r_list.push_back(vertex(WHITE, NULL, NULL)); 

(現在這些是你的問題外)

首先,NULL一般只用指針打交道時使用。由於distanceparent不是指針,使用0初始化它們,而不是NULL

//create the vertices 
vertex r = {WHITE, 0, 0}; 

其次,使用constants而不是#define

#define NUM_VERTICES 8 // <- bad 
const int NumberVertices = 8; // <- good 

最後,給你的枚舉的名稱,或地方它在一個命名空間:

enum Color { WHITE, GRAY, BLACK }; 

希望這些幫助!

1

您還沒有初始化it,所以你在隨機/未初始化的地方/指針插入。

將物品添加到std::list的正常方式包括其方法push_backpush_front;只有在您之前已確定要插入一個項目的特定地點時,通常纔會使用insert

2

首先,你是不是初始化it任何東西。你的意思是:

list<vertex*>::iterator it = r_list->begin(); 

另外,你爲什麼初始化一個int和char爲NULL?通常人們使用NULL作爲指針。

此外,如何命名你的枚舉和枚舉類型安全中受益,而不是利用他們作爲整數?

而且,沒有必要建立一個新的變量,使指針到頂點。當您撥打插入號碼時,您可以通過&r

而且,彼得指出,爲什麼不使用push_back()

您的代碼應該看起來更像是這樣的:


using namespace std; 

enum Color { 
    WHITE, 
    GRAY, 
    BLACK 
}; 

struct vertex 
{ 
    Color color; 
    int distance; 
    char parent; 
}; 

int main(int argc, char** argv) { 
    //create the vertices 
    vertex r = {WHITE, 0, ''}; 

    //create a list to hold the vertices 
    list* r_list = new list(); 

    list::iterator it = r_list->begin(); 
    r_list->insert(it, &r); 

    // Or even better, use push_back (or front) 
    r_list->push_back(&r); 
} 
2

您還沒有初始化的迭代器,所以它不是有效的使用插入。例如,您可以使用r_list->push_back(pr)

此外,在列表中的指針是不會一次R會熄滅的範圍內是有效的。很明顯,這不是一個問題,因爲它在main(),但我認爲這不是一個確切的例子,你將要使用的代碼,所以它可能會回來咬你...

+0

當我嘗試使用push_back()時,mingw編譯器給出了這個錯誤 錯誤:沒有匹配函數調用std :: list > :: push_back(vertex&)'| 但是,它並沒有給我那個錯誤,當我編譯它與g ++。無論如何,我認爲這個話題屬於另一個線程。 – unknown 2009-07-06 05:19:40

+0

該編譯器錯誤看起來像您可能試圖將頂點而不是頂點*傳遞到push_back方法中。但我可能是錯的... – Tom 2009-07-06 05:22:21