2016-06-19 2 views
0

나를 괴롭혀, C++을 처음 접했습니다. 나는 벡터에 저장된 값을 업데이트하기 위해 노력하고있어,하지만 난이 오류 받고 있어요 : 나는 그래서 비슷한 contains 및 다른 사람과 같은 방법을 (공유 할 수 std::vector 주위에 간단한 래퍼를 사용하고중첩 클래스 C++에서 값을 참조하고 업데이트해야합니다.

non-const lvalue reference to type 'Node' 

을 어떻게 ArrayList가 자바에 있는지). 다음과 같이

#include <vector> 

using namespace std; 

template <class T> class NewFrames { 

public: 

    // truncated ... 

    bool contains(T data) { 
     for(int i = 0; i < this->vec->size(); i++) { 
      if(this->vec->at(i) == data) { 
       return true; 
      } 
     } 

     return false; 
    } 

    int indexOf(T data) { 
     for(int i = 0; i < this->vec->size(); i++) { 
      if(this->vec->at(i) == data) { 
       return i; 
      } 
     } 

     return -1; 
    } 

    T get(int index) { 
     if(index > this->vec->size()) { 
      throw std::out_of_range("Cannot get index that exceeds the capacity"); 
     } 

     return this->vec->at(index); 
    } 

private: 
    vector<T> *vec; 

}; 

#endif // A2_NEWFRAMES_H 

이 래퍼를 활용 클래스는 정의 :

#include "Page.h" 
#include "NewFrames.h" 

class Algo { 

private: 
    typedef struct Node { 
     unsigned reference:1; 
     int data; 
     unsigned long _time; 

     Node() { } 

     Node(int data) { 
      this->data = data; 
      this->reference = 0; 
      this->_time = (unsigned long) time(NULL); 
     } 
    } Node; 

    unsigned _faults; 
    Page page; 
    NewFrames<Node> *frames; 
}; 

내가 벡터의 내부 Node 개체 중 하나를 참조해야 할 점에있어,하지만 난 필요 reference을 다른 값으로 변경할 수 있습니다. 다만 사용하여 내가 해봤

const Node &n = this->frames->get(this->frames->indexOf(data)); 

을 : 내가 SO에서 발견 한 바로는, 나는이 작업을 수행 할 필요가

Node n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

을 다음 디버거에서 데이터를 볼 수 있지만 값이 아닌 나중에 확인하면 업데이트됩니다. 이것을 고려해보십시오 :

const int data = this->page.pages[i]; 
const bool contains = this->frames->contains(Node(data)); 
Node node = this->frames->get(index); 
for(unsigned i = 0; i < this->page.pages.size(); i++) { 
    if(node == NULL && !contains) { 
     // add node 
    } else if(contains) { 
     Node n = this->frames->get(this->frames->indexOf(data)); 
     if(n.reference == 0) { 
      n.reference = 1; 
     } else { 
      n.reference = 0; 
     } 
    } else { 
     // do other stuff 
    } 
} 

루프의 후속 통과과 함께, 특정 데이터 값을 가진 노드는 다소 차이가납니다.

그러나 n.reference을 변경하려고 시도하면 const이 개체가 변경되지 않기 때문에 오류가 발생합니다. 이 노드를 변경하여 변경할 수있는 방법이 있습니까? 이런 일이 일어날 수있는 친숙한 자바 세상에서 나옵니다. 그러나이 이 C++에서이 아닌 이유를 알고 싶거나 이해하고 싶습니다.

+0

이것은 문제가되지 않지만 두 개의 연속 된 밑줄 ('__A2_NEWFRAMES_H__')과 밑줄과 대문자로 시작하는 이름은 구현에 예약되어 있습니다. 사용하지 마십시오. –

+0

불필요한 수동 메모리 관리를 피하기 위해'벡터 * vec;'를'벡터 vec;'로 대체해야합니다. – nwp

+0

Sigh. 문제를 보여주는 코드를 만들 때까지 코드를 자릅니다. 무엇이 잘못되었는지를 알아 내기 위해 이처럼 관련성이없는 모든 것들을 헤쳐 나갈 사람은 아무도 없을 것입니다. –

답변

0
Node n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

이 복사 frames에서 Node 격납 개체 n 복사. 사본을 수정해도 원래 노드는 변경되지 않습니다.

가장 간단한 "수정"은 참조를 사용하는 것입니다. 즉 T&T에서 get의 반환 유형을 변경하고, 코드가 작동하도록해야한다

Node& n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

에 앞의 두 라인을 변경하는 것을 의미한다. 그러나 코드에 너무 많은 간접적 인 지시가있어 아직 나타나지 않은 다른 문제가있을 수 있습니다. @nwp는 덧글에서 vector<T>* 대신 vector<T>을 사용하면 많은 두통을 줄일 수 있습니다.

그리고 스타일 어드바이스를하는 동안 this-> s를 제거하십시오. 그들은 단지 소음 일뿐입니다. 벨트 및 서스펜더의 유효성 검사를 간소화합니다. 0에서 vec.size()으로 루프를 돌릴 때 요소에 액세스 할 때 색인이 괜찮은지 확인할 필요가 없습니다. vec.at(i) ~ vec[i]으로 변경하십시오. 그리고 get에서 index이 범위를 벗어난 경우 vec.at(index)이 예외를 throw하므로 초기 범위 검사를 건너 뛰거나 실제 범위를 확인하도록 수정 한 후 검사를 계속하고 대신 vec[index]을 사용하십시오. vec.at(index)입니다.