2009-09-07 4 views
6

C++ STL 컨테이너를 사용할 때 어떤 조건에서 참조 값에 액세스해야합니까? 예를 들어 컨테이너에 대한 다음 함수 호출 후에 무효화 된 참조가 있습니까?STL 컨테이너의 지속 참조

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 
vector.push_back (3); 

vector[0] = 10;  //modifies 0'th element 

int& ref = vector[0]; 
ref = 10;    //modifies 0'th element 

vector.push_back (4); 
ref = 20;    //modifies 0'th element??? 

vector.clear(); 
ref = 30;    //clearly obsurd 
} 

stl의 대부분의 구현에서 이것이 작동한다는 것을 알고 있지만 표준 선언에 필요한 것에 관심이 있습니다.

--edit : 나는 C에 대한 (http://stxxl.sourceforge.net/) 라이브러리 ++ STXXL을 원했고,하지만 난 컨테이너에 의해 반환되는 참조를 변경하지 않고, 따라서 호환되지 여러 읽기를 통해 지속되지 있었고, 실현 becuase 임 관심 (그러나 피상적 인) 내 기존의 stl 코드. 예 : 난 그냥이 그 STXXL 용기를 의미 있는지 알고 싶어

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 


int& refA = vector[0]; 
int& refB = vector[1]; //refA is not gaurenteed to be valid anymore 
} 

경우 100 % 호환, 또는 실제로 나는 안전하지 않은/구현에 의존 방식으로 전체 시간을 STL 컨테이너를 사용하고 있었다면.

+2

FAQ에 대한 관련 답변을 찾았습니다. http://algo2.iti.uni-karlsruhe.de/dementiev/stxxl/trunk/FAQ.html "외부 메모리 데이터 구조의 요소에 대한 참조를 전달하거나 저장해서는 안됩니다. 참조가 사용될 때 요소를 포함하는 블록은 더 이상 내부 메모리에 없을 수 있습니다. "따라서 대답은 NO입니다. 컨테이너 요소에 대한 참조는 STL과 동일한 동작을하지 않습니다. – Akusete

+1

C++ 표준을 살펴보면 모든 컨테이너에는 기본 할당 자의 해당 typedef로 설정된 typedefs reference, const_reference, pointer 및 const_pointer가 있습니다. 표준위원회는 처음에는 refs와 포인터에 대한 추상화를 설정하여 프록시를 사용하여 컨테이너에서 (예 : 반복기가 이미있는 방식으로) 이러한 이벤트를 관리 할 수 ​​있지만 중단 된 것처럼 보였습니다. 표준 할당 자'allocator :: pointer'는'T *'등으로 typedef 자체를 궁극적으로 무의미하다고 생각합니다. –

+0

대부분의 STL 컨테이너의 인터페이스를 통해 읽음으로써 같은 감정을 갖게되었지만, 왜 그들이 절반 정도만 갔는지에 대한 토론을 찾을 수 없었습니다. – Akusete

답변

12

는 표준 23.2.4.3/1 말한다 다음 새로운 크기가 이전 용량보다 큰 경우

는 [insert()] 재 할당을 야기한다. 재 할당이 발생하지 않으면 모든 이터레이터와 참조점 이 삽입 포인터가 으로 유효하게 유지되기 전에 참조하십시오. 이 사실이 이야기이지만

(약 insert() 표 68 a.push_back(x) 모든 벡터 a 가치 x위한 a.insert(a.end(), x) 동등해야한다는 것을 나타낸다.) 즉, reserve() 메모리가 충분한 경우 미리 또는 push_back() 개 항목을 추가하면 반복기 및 참조가 무효화되지 않습니다.

항목은 제거 대해서는 23.2.4.3/3 말한다 :

[erase()]

은 소거의 시점 이후의 모든 반복자 및 참조를 무효화한다.

표 68, 각각의 표 67에 의하면, pop_back()clear()erase()는 적절한 호출 동등하다.

+0

젠장, 나는 디스크 백업 컨테이너의 100 % STL 호환 구현을 구현할 수 없다고 생각합니다. – Akusete

+1

참조를 자유롭게 만들고 유지할 수 있도록하려는 경우 아닙니다. 하지만 내 마음에, 다른 데이터 구조에있는 항목에 대한 장기적인 참조를 유지하는 것은 "iffy"관행입니다. 대신 반복자를 유지할 수없는 이유가 있습니까? –

+0

컨테이너의 구조체를 여러 번 변경하고 싶다면 종종 (나쁜 습관에서) 참조를 얻은 다음 참조를 수정하십시오. 매번 컨테이너를 통해 (특히 나무 기반 컨테이너를 사용하여) 컨테이너에 액세스하는 것보다 더 효과적이며 나중에 로컬 복사본을 작성하고 나중에 다시 쓰는 것보다 낫습니다. ... 그게 그 같은 habbit becuase, 그리고 내 지식을 참조의 유효한 사용했다, 그 사용은 심각한 오류가 발생할 것이라고 라이브러리를 사용하여 피곤했다 (또한) 발견되지 않을 것입니다 – Akusete

1

나는 참조가 (또한 max_size, capacityreserve 방법 참조) 명시 적 또는 resize() 암시 만이 무효화 될 것이라고 기대한다.

+0

동의 함. 왜 메모리를 무효로 할까? 단순히 null로 설정하거나 비슷하게 설정합니다. – jkeys

+0

@Hooked : 그 행동에 의존하는 것은 불가능합니다. C++ 표준 라이브러리 구현은 2003 C++ ISO 표준에 제시된 의미 규칙을 준수하면 원하는대로 자유롭게 수행 할 수 있습니다. –

1

벡터는 현재 용량에 따라 재 할당 할 때 iterator와 참조를 무효화합니다. 위의 코드가 작동하는 경우도 있지만, push_back (4) 호출 후에 참조가 무효화 될 수 있으므로이 방법을 사용해서는 안됩니다. 벡터

7

몇 가지 기본 규칙 :

  • 재 할당이 벡터의 요소에 대한 모든 참조, 포인터, 반복자 을 무효화합니다.
  • 삽입 참조, 포인터 및 이터레이터 을 무효화 할 수 있습니다.
  • 요소 삽입 또는 제거 은 요소를 참조하는 참조 자, 포인터 및 반복기를 무효화합니다.
  • 삽입으로 인해 재 할당이 발생하는 경우 은 모든 참조, 반복자 및 포인터를 무효화합니다. 벡터 내로 삽입하는 방법에 대한
+1

* 충분한 공간을 확보 한 경우 삽입시 재 할당이 발생하지 않도록 보장됩니다 (분명하지만 중요하지만). –

관련 문제