2014-01-22 3 views
0

Я пытаюсь написать программу списка смежности с помощью C++. Итак, для этого я использую вектор списка, и каждый список содержит вершину, список смежности которой сопровождается другими членами, связанными с ней, в неориентированном графе в терминах класса Node нижеРазница в поведении с использованием обычного указателя и shared_ptr

Вот структура узла, которую я использую:

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 обновляется в каждом из списка, как и при посещении Vertex. Поэтому я хочу использовать указатель вместо сохранения по значению. Проблема заключается в том, что я сохраняю указатель на вершину выше в узле как 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

Должно быть просто

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 в обычной версии указателя нет необходимости в операции «& (*» либо, он просто работает, потому что они компенсируют.

+0

Но (* mVertices) [e.mEnd.mId-1] - это вершина, а не указатель на вершину. –

+0

Хорошо, я сделал mVertices типа vector >, а затем он работает хорошо. Раньше его тип был всего лишь вектором . –

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

Смежные вопросы