列表向量的正确构造函数是什么

时间:2013-12-21 05:24:48

标签: c++ oop vector constructor

我正在研究一些关于如何为向量构建一个合适的构造函数的例子,我仍然对如何实际实现它感到困惑。使用给定的类......

class Graph
{
private:
    class Edge
    {
    public:
        Edge(string vertex, int weight)
        {
            m_vertex = vertex;
            m_weight = weight;
        }
        ~Edge(){}
        string m_vertex;
        int m_weight;
    };
    vector< list<Edge> > adjList; //vector of lists
public:
    Graph();
    ~Graph();
    vector < list < Edge > > get_adjList(){return adjList;}
    //Other functions....

};

我仍然不确定在构造函数中放入什么Graph::Graph()我尝试过做一些事情,例如

Graph::Graph()
{
    new vector < list < Edge > >;
}

但我被告知这会导致内存泄漏。我以前只为链表制作了构造函数,直到现在才需要向量。我可以清楚地说明如何为列表向量创建构造函数。我需要构造函数,所以我可以访问其他文件中的adjList(列表的向量),以便复制它。

4 个答案:

答案 0 :(得分:3)

Graph构建vector< list< Edge > > adjList时,Graph已经有一个成员new可供您分配和构建。您不需要编写任何进一步的构造函数。

此处对Graph::Graph() { new vector < list < Edge > >; // DELETE THIS LINE } 的调用可以完全删除:

vector< list< Edge > >

就目前而言,它分配一个完全独立的new,然后抛弃adjList返回的指针。但是,从各方面来看,无论如何你都不需要它。您的new成员已经在那里,空着并等待数据。您无需致电adjList或其他任何内容。

需要的是填充Graph::Graph()成员的某种方式。您可以在get_adjList()或外部代码中执行此操作。

您当前的getter函数adjList当前返回vector < list < Edge > >& get_adjList() {return adjList;} 副本,而不是引用。您可以考虑更改该方法以返回引用:

vector < list < Edge > >* get_adjList() {return &adjList;}

或指针:

get_adjList()

以便类外的代码可以调用Graph my_graph; vector< list<Edge> >& adjList = my_graph.get_adjList(); // Make a graph with two nodes, both pointing at each other, with weight 10 adjList.resize( 2 ); // make room for two nodes adjList[0].push_back( Edge( 1, 10 ) ); adjList[1].push_back( Edge( 0, 10 ) ); 然后操作类中的字段。

这样的事情:

vector< list<Edge> >

要防止手指一遍又一遍地输入typedef,您可以在class Graph内添加class Graph { public: typedef vector< list< Edge > > adj_type; // ... };

Graph::adj_type& adjList = my_graph.get_adjList();

然后在外面,你可以这样说:

adj_type

如果您稍后更改代码,那么还会将其余代码与Graph的确切定义隔离开来。

您最终应考虑向class Graph { //... public: void add_vertex( unsigned id ) { if (id > adjList.size() ) adjList.resize( id ); } void add_edge( unsigned from_id, unsigned to_id, int weight ) { adjList[fromId].push_back( Edge( to_id, weight ) ); } } 添加方法以添加顶点和边。类似的东西:

m_vertext

未经测试的代码,但您希望得到这个想法。

最后一个想法:Edge为什么map< string, list<Edge> >中有一个字符串?我刚注意到这一点,看起来很奇怪。

如果您的顶点是非数字的,那么您应该考虑使用vector代替adjList map<string, unsigned>。或者添加{{1}}以将字符串映射到ID。否则,您将无法有效地将边缘追逐到顶点。

答案 1 :(得分:0)

如果您创建new的实例(这不是Java),则不需要使用adjListvector已经是堆栈上的Graph变量我认为默认的矢量构造函数就足够了,不需要明确地调用它。仅当您的变量是指针时才需要调用new

但您可能需要将get_adjList的返回类型更改为仅返回adjList的引用,而不是adjList的新副本。

class Graph
{
private:
    vector<list<Edge> > adjList; //vector of lists
public:
    Graph();
    ~Graph();
    vector<list<Edge> > &get_adjList(){return adjList;}
};

或者如果您需要的是vector元素,最好不要返回vector,只需根据查询索引返回元素,例如:

list<Edge> &get_adjListElmt(int idx){return adjList[idx];}

答案 2 :(得分:0)

如果您的图表类可以从文件中读取,那么该类的构造函数可能类似于:

Graph::Graph(istream &iss)
{
    // number of vertices in the graph
    // where each vertex has a list of edges
    size_t vertices;
    iss >> vertices;
    adjList.resize(vertices);
    ...
}

除了设置向量的大小之外,不需要为向量动态分配空间,除非您将向量声明为类中的指针。

现在,为了获取向量的访问权限,您可以在类中创建一个getter方法,该方法返回向量的副本(如果您不希望对原始文件进行变异),或者getter可以返回一个引用/指针到实际的对象

我前后实现了一个图表类,您可能想要查看的另一个选项是可以创建给定densitymaxedgeLengthnumberofvertices的随机图形对象的构造函数

答案 3 :(得分:0)

我同意@ joe-z。但是,我认为问题可能是他需要一定大小的矢量。

struct Edge {  // you could template this to make more generic.
    int v2;
    double weight;
};
class Graph {
public:
    Graph(size_t size) : m_adj_list(size) {}
    void AddEdge(int v1, int v2, double weight) {
        m_adj_list[v1].emplace_back(v2, weight);
    }
    void Resize(size_t size) {
        m_adj_list.resize(size, std::vector<Edge>());
    }
private:
    // You can use a list but in general a vector might be a better choice
    std::vector<std::vector<Edge>> m_adj_list;
};

另外。不要只使用裸指针。使用std :: unique_ptr或std :: shared_ptr。通常,您可以使用规则(按此顺序):

  1. 不要使用指针(std :: vector已经负责你的内存管理)
  2. 使用unique_ptr
  3. 使用shared_ptr
  4. 在不接受/代表所有权时使用裸指针,而您无法传递shared_ptr