2012-11-24 4 views
2

벡터와 비슷한 클래스를 만들고 있습니다. 자체 알고리즘을 사용하여 데이터가 실제로 저장되는 위치와 방법을 결정합니다. 사용자의 입장에서 보았을 때, 이것은 법선 벡터처럼 작동합니다.사용자 정의 벡터 클래스에 대한 연산자 [] 오버로드

내부적으로 중복 값을 두 번 이상 저장하지 않아 메모리를 절약하려고합니다. 같은 값이 벡터에 두 번 이상 푸시된다면 인덱스를 사용하여 멋진 댄스 동작을하지만 실제 값만 저장합니다.

연산자 []을 (를) 오버로드하면 인덱스 인수가 "실제"색인으로 변환되므로 데이터가 실제로 저장되는 위치에 액세스 할 수 있습니다.

사용자 그래서 같은 요소에 액세스하려고 시도하는 경우 :

int i = svec[8]; 

올바른 요소는 "실제"인덱스 8 변환 소자 올바른 액세스하여 반환된다.

문제는 사용자가과 같이 값을 할당 할 때 온다 :

svec[8] = 1; 

값 8 다시 "진짜"인덱스에 포함되며 요소에 대한 참조는 operator[]()에 의해 반환됩니다. 그러나 여러 색인이 해당 요소에 매핑되어있을 수 있습니다. 참조를 반환하고이를 변경할 수있게하면 다른 인덱스의 값을 변경하는 바람직하지 못한 부작용이 있습니다.

값으로 요소를 반환 한 경우 연산자 []를 사용하여 값을 할당 할 수 없습니다.

operator[]() 내에서 작업을 수행하면 요소의 값을 변경하여 새로운 요소를 만들 수 있고, 색인을 사용하여 멋진 댄스 동작을 만들 수 있으며 새로운 요소에 대한 참조를 반환 할 수 있는지 알고 싶습니다.

이게 가능합니까? 그렇지 않으면 사용자가 []을 사용하여 값을 수정하지 못하도록 값으로 반환해야하는 것처럼 보입니다.

답변

3

클래스가 메서드 change_element을 가지고 있고 모든 사람이이 함수를 호출 할 때 쉽게 변경 될 수 있습니까? 그렇습니다.

template <typename T> 
struct my_vec { 
    T& change_element(int index, T new_value) 
    { ... } 
}; 

이제 아이디어는 당신을 위해이 일을 operator[]에서 프록시 클래스를 반환하는 것입니다.

// inside my_vec: 
    struct proxy { 
    my_vec *vec; 
    int index; 

    T& operator=(T o) 
    { return vec->change_element(index, std::move(o)); } 

    operator T() const { return (*const_cast<my_vec const*>(vec))[index]; } 
    }; 

    proxy operator[](int i) { return proxy{this, i}; } 
    T const& operator[](int i) const { ... } 

오버 헤드가 없기 때문에 모든 공용 컴파일러는 프록시 요소를 멀리 떨어져 최적화해야합니다.

이 트릭은 STL에서 vector<bool>으로 심지어 사용됩니다. 좀 더 완벽한 예를 들어 보겠습니다.

+0

좋은 점 : http://www.sgi.com/tech/stl/stl_bvector.h : ** _ Bit_reference ** –

+0

그건 좋은 작은 트릭입니다. 공유해 주셔서 감사합니다. – user974967

0

변환 연산자가있는 클래스를 요소에 변경해야한다는 것을 벡터에 알리는 형식 및 부 합성 연산자를 반환 할 수 있습니다.