结构转发列表项目是否会消失?

时间:2017-03-04 14:39:11

标签: c++ pointers forward-list

这段代码让我很紧张。已经调试了一段时间,不能相信我对c ++有多生疏。

我正在尝试对图表进行建模,以便运行一些简单的算法,但这似乎并没有那么好用。每个顶点都包含一个前向列表给他的邻居,但是当插入它们明显存在的元素时..直到我到达打印功能;那时前锋名单是空的。

我已尝试使用new分配forward_list,因为作用域可能是对它的解释..也没有运气......

#include <iostream>
#include <vector>
#include <set>
#include <forward_list>
#include <fstream>

using namespace std;

typedef struct Vertex Vertex;

struct Vertex {
    unsigned id;
    forward_list<Vertex*>_next;

    bool operator < (const Vertex &other) const { return id < other.id; };
};

typedef set<Vertex> Graph;
typedef vector<Vertex*> Index;
typedef pair<unsigned, unsigned> Edge;
typedef forward_list<Vertex*> Neighbors;


// Function:    process_line()
// Purpose:     process a specific line from the file.
// Params:      line to process
Edge process_line(string line){
    unsigned vertex_from;
    unsigned vertex_to;

    int idx = line.find(" ");

    vertex_from = (unsigned)stoul(line.substr(0, idx));
    vertex_to = (unsigned)stoul(line.substr(idx+1, line.length()));

    return make_pair(vertex_from, vertex_to);
}


// Function:    load_graph()
// Purpose:     load graph from file in relation
// Params:      path, and reference to graph and index
bool load_graph(string file_path, Graph &graph, Index &index){
    string line;
    ifstream file(file_path);
    bool foundEmptyLine = false;

    if(file.is_open()){
        while(getline(file, line)){
            if(line.empty()){
                foundEmptyLine = true;
                continue;
            }

            if(!foundEmptyLine){
                // processing vertexes
                Vertex *vertex = new Vertex;

                vertex->id = stoul(line);
                graph.insert(*vertex);
                index.emplace_back(vertex);
            }else{
                //Processing relations
                Edge edge = process_line(line);

                Vertex* neighbor = index.at(edge.second);
                Vertex* source = index.at(edge.first);

                // Lookup edge in index
                source->_next.emplace_front(neighbor);

                // ITEMS PRESENT! <----------------------
            }
        }
        file.close();
    }else{
        cout << "Unable to open " << file_path;
        return false;
    }

    return true;
}


void print_graph(Graph &graph){
    for(Graph::iterator it = graph.begin(); it != graph.end(); ++it){
        Neighbors neighs = it->_next;

        cout << "Node: " << it->id << " neighbors: " neighs.empty();

        cout << endl;
    }
}


// Entry point.
int main() {
    Graph graph;
    Index index;

    load_graph("graph_1.txt", graph, index);
    print_graph(graph);
}

2 个答案:

答案 0 :(得分:1)

这又是昨天的问题。

让我们试着概括一下std::set

  • 从C ++ 11开始,iterator的{​​{1}}始终是std::set的迭代器。这是因为当我们更改const value_type的条目时,此条目需要放在数据结构中的其他位置。
  • 当我们在std::set中插入内容时,会提供两个签名:

    std::set

    但无论如何,插入副本元素移动到容器中。

所以在你做的情况下

pair<iterator,bool> insert (const value_type& val);
pair<iterator,bool> insert (value_type&& val);

首先你分配内存(你永远不会删除它!你会泄漏很多内存,你可以使用valgrind检查)。然后将顶点的副本插入Vertex *vertex = new Vertex; vertex->id = stoul(line); graph.insert(*vertex); index.emplace_back(vertex); 并将分配的内存的指针插入std::set

等你以后再做

std::vector

从矢量中取出顶点(请记住,这是您使用Vertex* neighbor = index.at(edge.second); Vertex* source = index.at(edge.first); // Lookup edge in index source->_next.emplace_front(neighbor); 分配的顶点)。并将另一个顶点(也是动态分配的)插入其new但是:它们与std::forward_list中的顶点无关。

所以当你稍后通过你的std::set

std::set

这与插入边缘时所做的完全无关 - 并且所有for (Graph::iterator it = graph.begin(); it != graph.end(); ++it) 都是空的。

附注

  • 这是你必须在C中使用的东西,而不是在C ++中使用的东西!

    std::forward_list
  • 你应该把它放在上面:

    typedef struct Vertex Vertex;
    

    在声明typedef forward_list<Vertex*> Neighbors; 之后声明Neighbors的类型没有意义,因为_next具有此类型。

  • 尽可能使用_next,并尽可能const / cbegin(我昨天已经告诉过您),例如:

    cend

    此处没有任何区别,但如果您在某个时候更改for(Graph::iterator it = graph.cbegin(); it != graph.cend(); ++it){ 的类型,graph可能会将迭代器返回begin()而不是value_type

答案 1 :(得分:0)

修改图形以保持对现有顶点的引用。我仍然不确定为什么要修复它 - 但感觉就像是在进行单挑。