[英]Difference in behavior using normal pointer and a shared_ptr
我一直在嘗試使用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));
}
應該只是
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 -它獲取對象,在堆上復制它,並創建指向該副本的新共享指針,實際上是在此處復制對象。 您只想傳遞共享指針(按值或const ref)。
PS在常規指針版本中也不需要“&(*”操作,因為它們被抵消了,所以它只能工作。
這是因為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]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.