使用普通指针和shared_ptr的行为差异

时间:2014-01-22 16:46:19

标签: c++ 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));
    }

2 个答案:

答案 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]