2012-06-07 4 views
-1

두 개의 노드 포인터 벡터가 있습니다.포인터를 const로 만들기 C++

vector<Node*> tmp; 

vector<Node*> nodes; 

내가 delete nodes는 다음 tmp도 삭제되면 나는 tmp = nodes;

을 말한다.

nodes을 수정할 때마다 tmp을 수정할 수 없습니까?

나는 기본적으로 Dijkstra 's를 실행 중입니다. 그러나이 알고리즘은 최단 경로를 결정할 때 항상 노드 벡터를 삭제합니다. 즉, 출발지에서 목적지까지 최단 경로 만 한 번만 수행 할 수 있습니다. 나는 그래프 0 ---> 1 ---> 2 ---이있는 경우 nodes 포인터 아니므로

> 즉

CGraph g; 

g.Dijkstras(0); 
g.PrintShortestRouteTo(2); 
g.Dijktras(2);   
g.PrintShortestRouteTo(3); <-- source is still 0 since nodes is deleted 
            therefore I get the path from 0 to 2 


    class Node 
{ 
public: 
    Node(int id) 
     : id(id), previous(NULL), 
     distanceFromStart(INT_MAX) 
    { 
     nodes.push_back(this); 
    } 
public: 
    int id; 
    Node* previous; 
    int distanceFromStart; 
}; 

vector<Node*> nodes; 

void CGraph::Dijkstras(int source) 
{ 

    nodes[source]->distanceFromStart = 0; 


    for (int i = 0; i < (int)nodes.size(); i++) 
     cout << nodes[i]->distanceFromStart << " " ; 

    cout << "------------------------" << endl; 

    while (nodes.size() > 0) 
    { 
     Node* smallest = ExtractSmallest(nodes); 
     //cout << "Smallest: " << smallest->id << " "; 
     //Node* smallest = nnodes[1]; 
     vector<Node*>* adjacentNodes = 
      AdjacentRemainingNodes(smallest); 
     const int size = adjacentNodes->size(); 
     for (int i=0; i<size; ++i) 
     { 
      Node* adjacent = adjacentNodes->at(i); 
      int distance = Distance(smallest, adjacent) + 
       smallest->distanceFromStart; 
      if (distance < adjacent->distanceFromStart) 
      { 
       adjacent->distanceFromStart = distance; 
       adjacent->previous = smallest; 
      } 
     } 
     delete adjacentNodes; 
    } 
} 
+2

'delete nodes'는 컴파일되지 않으며,'nodes'는 포인터가 아닙니다. – GManNickG

+0

'벡터 * tmp'을 의미 했습니까? – iammilind

+0

예, nodes는 포인터입니다. 나는 그것을 고정했다 – CyberShot

답변

1

3 당신은 delete nodes을 쓸 수 없습니다. 이 코드를 작성하면 코드가 컴파일되지 않습니다.

vector<Node*> tmp = nodes; 

는 다음 벡터 객체의 복사본, 벡터 아닌 내용을합니다

당신이 쓸 때. 벡터의 내용은 벡터의 두 사본에서 동일합니다. 따라서 한 벡터에서 내용을 변경하면 변경 내용은 다른 벡터 사본에도 반영됩니다. 당신은 또한 내용의 사본을 확인하려면

,이 쓰기 :

std::vector<Node*> tmp; 
tmp.reserve(nodes.size()): 

//include <algorithm> for std::transform 
std::transform(nodes.begin(), 
       nodes.end(), 
       std::back_inserter(tmp), 
       [](Node const *node) { return new Node(*node); }); 

참고 :이 람다 표현식을 사용으로는 위의 코드는 C++ 11 만에서 컴파일됩니다. C++ 03에서는 함수 나 함수를 대신 사용할 수 있습니다.

std::unique_ptr<Node> 또는 std::shared_ptr<Node>과 같은 스마트 포인터를 Node* 대신 사용하는 것이 좋습니다. 스마트 포인터는 메모리 자체를 관리하기 때문에 걱정할 필요가 있습니다. 그러나 스마트 포인터를 사용하면 위의 코드는 약간 다르지만 내용을 복사하려면 기본 아이디어가 동일합니다. 이 관리하는

+0

구문에 대해 확실합니까? 나는 '['앞에 ']'앞에 그리고 'const'에 앞서 예상되는 일차 표현식을 얻는다. – CyberShot

+0

@CyberShot : *** 참고 : ** 위 코드는 람다 식을 사용하므로 C++ 11에서만 컴파일됩니다. C++ 03에서는 함수 또는 함수를 대신 사용할 수 있습니다. * – Nawaz

+0

함수 대신에 함수 또는 functor는 정확히 무엇입니까? – CyberShot

0

한 가지 방법은 공유 포인터를 사용하는 대신

vector<shared_ptr<Node> > tmp; 

그 tmp를/노드는 객체 (어떤 노드 * 점) 여전히 존재하는 다른 전 범위를 벗어나 길 경우에도 마찬가지입니다.

0

당신은 가능성이 루프가

tmp.clear(); 

for(vector<Node*>::iterator it = nodes.begin(); it != nodes.end(); it++) 
{ 
    Node* copy = new Node((*it)); 

    tmp.push_back(copy); 
} 
+0

나는 이것을 시도했지만 어떤 이유로 Node *에서 int 로의 잘못된 변환을 얻는다. 심지어 여기서 int를 볼 수는 없지만 – CyberShot

+0

@CyberShot : 코드를 게시하십시오. – Nawaz

+0

나는이 프로그램을 실행 한 후에 노드를 삭제 한 후에도 tmp가 수정되었다. 이것은 tmp와 노드가 여전히 연결되어 있음을 의미하지만, 나는 그것들을 독립적으로 원한다. – CyberShot

0

귀하의 질문에 대한 TMP로 각 항목을 복사 "노드"를 통해 다음 클래스의 약간의 혼란,하지만 내 경우 노드의 복사 생성자를 구현해야합니다 해석은 다음과 같습니다

std::vector<Node *> *tmp; 
std::vector<Node *> *nodes; 

nodes = somehow_gets_dynamically_created_vector(); 
tmp = nodes; 
// perhaps do other things with nodes 
delete nodes; 

그런 다음, 코드 (즉, 그것은 해제 된 메모리를 가리키는) 매달려 tmp을 떠난다. 그러나.이 안전해야 :

std::vector<Node *> tmp; 
std::vector<Node *> *nodes; 

nodes = somehow_gets_dynamically_created_vector(); 
tmp = *nodes; 
// perhaps do other things with nodes 
delete nodes; 

지금, 당신의 샘플 코드, 당신은 무엇을 설명 막연하게 비슷 유일한 코드는 코드가 adjacentNodes 변수를 처리하는 방법입니다. 그리고 delete adjacentNodes 행의 결과로 nodes에 나쁜 일이 발생합니다. AdjacentRemainingNodes 기능이 사용자가 생각하는대로 작동하는지 확인합니다. 적어도 함수의 본체 내에서 실행되는 코드 어딘가의 new std::vector<Node *>에 대한 호출에서 제공된 값을 반환해야합니다. 그렇지 않은 경우 delete (adjacentNodes)이 잘못되었습니다.

그러나 아마도 당신은 다른 의미를 염두에 두었을 것입니다. 대신 nodestmp에 복사 한 후 tmp은 업데이트 된 값이 distantFromStart으로 표시된다는 것을 의미하면 포인터 사용의 결과입니다. 당신은 당신의 벡터에서 포인터를 사용하지 않음으로써 그 문제를 피할 수 있습니다.

std::vector<Node> tmp; 
std::vector<Node> nodes; 

tmp = nodes; 

그러나, 당신은 복사 생성자를 정의하거나 그렇지 않으면 previous 멤버 처리하는 방법을 파악해야합니다. 예를 들어 복사 생성자는 LHS에서 값을 복사하는 대신 previous 멤버를 NULL으로 설정할 수 있습니다.

Node::Node (const Node &lhs) 
    : id(lhs.id), previous(NULL), distanceFromStart(lhs.distanceFromStart) 
{} 

하지만 적절한 것을해야합니다.

관련 문제