簡體   English   中英

使用普通指針和shared_ptr的行為差異

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM