문제

나는 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);
}
도움이 되었습니까?

해결책

여기에는 몇 가지 문제가 있습니다.

우선, 당신은 다른 사람이 말한 것처럼 반복기를 초기화하지 않습니다.

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

이것을하면 코드가 괜찮을 것입니다. 그러나 코드는 나쁜 방식으로 수행됩니다.

힙에서 목록을 할당하는 이유는 무엇입니까? 코드보기 : 메모리 누출이 있습니다. 당신은 전화하지 않습니다 delete r_list 어딘가에. 이것이 스마트 포인터를 사용해야하는 이유입니다 (std::unique_ptr, std::shared_ptr C ++ 11이있는 경우 그렇지 않으면 등가물을 향상시킵니다. boost::scoped_ptr 그리고 boost::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);

또한 반복자를 사용하여 삽입하는 것은 먼 길을 가고 있습니다. 그냥 사용하십시오 푸시 프론트 () 또는 푸시 뒤로 ():

//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 각 요소에서. 이 문제는 사용하여 도움이됩니다 포인터 컨테이너 라이브러리 부스트.

그러나 가장 좋은 방법은 정점을 직접 저장하는 것입니다 (그들에게 포인터가 아닌).

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

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

r_list.push_back(r);

Vertex를 생성자에게 제공하는 경우, 당신은 그것들을 내내 건설 할 수도 있습니다.

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은 일반적으로 포인터를 다룰 때만 사용됩니다. 부터 distance 그리고 parent 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 };

이 도움을 바랍니다!

다른 팁

반복기를 초기화하지 않았으므로 삽입하는 것이 유효하지 않습니다. 당신은 사용할 수 있습니다 r_list->push_back(pr) 대신, 예를 들어.

또한 R이 범위를 벗어나면 목록의 포인터는 유효하지 않습니다. 분명히이 경우에는 문제가되지 않습니다. main(), 그러나 나는 이것이 당신이 코드를 사용하는 정확한 예가 아니라고 가정합니다. 그래서 그것은 당신을 물기 위해 돌아올 수 있습니다 ...

우선, 당신은 초기화하지 않습니다 it 무엇이든. 당신은 다음을 의미합니까 :

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

또한 왜 int와 char를 null로 초기화합니까? 일반적으로 사람들은 포인터에 null을 사용합니다.

또한, 열거의 이름을 지정하고 열거의 유형 안전을 통해 ints로 사용하는 대신에 어떻게 혜택을 받는가?

또한 정점에 대한 포인터를 만들기 위해 새로운 변수를 만들 필요가 없습니다. 인서트를 호출하면 통과 할 수 있습니다 &r.

또한 Peter가 지적한 것처럼 왜 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);
}

초기화되지 않았습니다 it, 그래서 당신은 무작위/비 초기 장소/포인터에 삽입하고 있습니다.

a에 항목을 추가하는 정상적인 방법 std::list 방법을 포함하십시오 push_back 그리고 push_front; 일반적으로 사용합니다 insert 이전에 다른 항목을 하나 더 삽입하려는 특정 지점을 결정한 경우에만 가능합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top