STL List用于保存结构指针

unk*_*own 4 c++ pointers stl list segmentation-fault

我有一个名为vertex的结构,我创建了一些指向它们的指针.我想要做的是将这些指针添加到列表中.下面的代码,当它试图将指针插入列表时,会产生分段错误.有人可以解释一下发生了什么吗?

#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);
}
Run Code Online (Sandbox Code Playgroud)

GMa*_*ckG 10

这里有几个问题.

首先,你没有初始化迭代器,就像其他人说的那样:

list<vertex*>::iterator it = r_list->begin();
Run Code Online (Sandbox Code Playgroud)

这样做,你的代码就可以了.但是你的代码是以糟糕的方式完成的.

为什么要从堆中分配列表?看看你的代码:你有内存泄漏.你不是delete r_list在任何地方打电话.这就是为什么你应该使用智能指针(std::unique_ptr,std::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);
Run Code Online (Sandbox Code Playgroud)

另外,使用迭代器插入是很重要的事情.只需使用push front()push back():

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

r_list.push_back(pr);
Run Code Online (Sandbox Code Playgroud)

另一件事:如果你的列表比你构建的顶点更长,它将指向无效的东西.

例如:

// 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.
Run Code Online (Sandbox Code Playgroud)

一种解决方案是存储指向堆分配顶点的指针:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

现在,即使在函数之后,列表也指向一个有效的堆分配顶点.现在有一个问题,当你完成使用列表时,你需要通过lsit并调用delete每个元素.使用Boost指针容器库可以解决此问题.

但最好的方法是只存储顶点(而不是指向它们的指针):

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

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

r_list.push_back(r);
Run Code Online (Sandbox Code Playgroud)

如果给顶点一个构造函数,你甚至可以就地构造它们:

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));
Run Code Online (Sandbox Code Playgroud)

(这些现在不在您的问题中)

首先,NULL通常仅在处理指针时使用.由于distanceparent不是指针,用于0初始化它们,而不是NULL:

//create the vertices
vertex r = {WHITE, 0, 0};
Run Code Online (Sandbox Code Playgroud)

其次,使用constants而不是#define:

#define NUM_VERTICES 8 // <- bad
const int NumberVertices = 8; // <- good
Run Code Online (Sandbox Code Playgroud)

最后,为枚举命名,或将其放在命名空间中:

enum Color { WHITE, GRAY, BLACK };
Run Code Online (Sandbox Code Playgroud)

希望这些帮助!