我一直在尝试使用c ++编写邻接列表程序。 所以为此,我使用了一个列表向量,每个列表包含顶点,它的邻接列表后面跟着一个无向图中连接到它的其他成员,下面是Node类
这是我使用的Node结构:
typedef vector<shared_ptr<list<Node>>> VecSPLisNode;
typedef vector<Vertex> VecVertex;
class Graph {
shared_ptr<VecVertex> mVertices;
shared_ptr<VecSPLisNode> mVecNodeList;
void addEdge(const Edge& e);
}
class Edge {
public:
Vertex mStart, mEnd;
int mWeight;
public:
Edge(Vertex start=-1, Vertex end=-1, int wt=-1) :
mStart(start), mEnd(end), mWeight(wt) {
}
};
class Vertex {
public:
int mId;
bool mVisited;
public:
Vertex(int info=-1, bool visited=false) : mId(info), mVisited(visited) {
}
};
现在我想保存相同的顶点实例,以便在访问顶点时,在每个列表中更新其mVisited。所以我想使用指针而不是按值保存。问题是如果我将指向节点上方的顶点的指针保存为shared_ptr,即使我将指针更新为访问的特定顶点,在另一个列表中顶点仍然是未访问的。但是普通指针也不会发生同样的事情。 以下是我这样做的两种方式。
shared_ptr方式:
class Node {
public:
shared_ptr<Vertex> vert;
int weight;
Node(shared_ptr<Vertex> v, int wt) :vert(v), weight(wt) {}
};
void Graph::addEdge(const Edge& e) {
((*mVecNodeList)[e.mStart.mId-1])->push_back(Node(make_shared<Vertex>((*mVertices)[e.mEnd.mId-1]), e.mWeight));
((*mVecNodeList)[e.mEnd.mId-1])->push_back(Node(make_shared<Vertex>((*mVertices)[e.mStart.mId-1]), e.mWeight));
}
指针方式:
class Node {
public:
Vertex* vert;
int weight;
Node(Vertex* v, int wt) :vert(v), weight(wt) {}
};
void Graph::addEdge(const Edge& e) {
((*mVecNodeList)[e.mStart.mId-1])->push_back(Node(&((*mVertices)[e.mEnd.mId-1]), e.mWeight));
((*mVecNodeList)[e.mEnd.mId-1])->push_back(Node(&((*mVertices)[e.mStart.mId-1]), e.mWeight));
}
答案 0 :(得分:2)
应该只是
void Graph::addEdge(const Edge& e) {
((*mVecNodeList)[e.mStart.mId-1])->push_back(Node((*mVertices)[e.mEnd.mId-1], e.mWeight));
((*mVecNodeList)[e.mEnd.mId-1])->push_back(Node((*mVertices)[e.mStart.mId-1], e.mWeight));
}
你的错误是使用make_shared - 它需要对象,在堆上复制它并创建指向该副本的新共享指针,你基本上在这里复制你的对象。你只想传递你的共享指针(通过value或const ref)。
P.S在常规指针版本中,不需要“&amp;(*”操作,它只是起作用,因为它们取消了。
答案 1 :(得分:2)
这是因为make_shared<T>(arg...)
是std::shared_ptr<T>(new T(arg...))
的优化速记。您在此处复制了Vertex
并修改了副本。
因此,您应该将make_shared<Vertex>((*mVertices)[e.mEnd.mId-1])
替换为(*mVertices)[e.mEnd.mId-1]
。