2009-07-06 67 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