2011-03-23 2 views
1

이 예제에서는 정수가 하나있는 벡터를 만든 다음 벡터에서 해당 정수를 지 웁니다. 벡터의 크기는 감소하지만 정수는 여전히 존재합니다! 정수가 아직 왜 있습니까? 크기 0의 벡터가 요소를 포함하는 것은 어떻게 가능합니까?C++의 stl 벡터에서 방금 지운 요소에 액세스 할 수있는 이유는 무엇입니까?

#include <vector> 
#include <iostream> 

using namespace std; 

int main(int agrc, char* argv[]) 
{ 
    vector<int> v; 
    v.push_back(450); 

    cout << "Before" << endl; 
    cout << "Size: " << v.size() << endl; 
    cout << "First element: " << (*v.begin()) << endl; 
    v.erase(v.begin()); 
    cout << "After" << endl; 
    cout << "Size: " << v.size() << endl; 
    cout << "First element: " << *(v.begin()) << endl; 

    return(0); 
} 

출력 :

Before 
Size: 1 
First element: 450 
After 
Size: 0 
First element: 450 

답변

3

IIRC 벡터는 특별히 말하지 않는 한 공간을 해제하지 않으므로 여전히 메모리에 있지만 벡터에 의해 추적되지 않는 항목을 보게됩니다. 이것은 크기를 먼저 확인해야하는 이유 중 일부입니다 (다른 것을 지정하지 않으면 쓰레기 포인터를 역 참조하게됩니다).

+1

벡터의 끝 (기존에는 삭제되었지만 삭제 된 요소 포함)을 넘어서는 요소에 액세스하려는 것은 정의되지 않은 동작 (예 : 오류)이므로 운이 좋다면 구현이 응용 프로그램을 중단시킬 수 있다는 점에 유의해야합니다. 문제를 디버그하십시오. 이 행동에 전혀 의존 할 수는 없습니다. –

+0

@David : 그렇습니다.하지만이 경우에는 분명하다고 생각할 것입니다. OP는 왜 코어를 버리지 않았는 지 묻고있었습니다. – geekosaur

10

당신은 잘못된 메모리 위치를 역 참조에 의해 정의되지 않은 동작을 호출한다. 일반적으로 효율성을 위해 힙 관리자는 delete을 사용하여 삭제 된 메모리를 즉시 해제하지 않습니다. 그러나 그 메모리 위치에 액세스 할 수 있다는 의미는 아니며, 힙 관리자는 언제든지이 메모리 위치를 다른 용도로 사용할 수 있습니다. 따라서 잘못된 메모리 위치를 역 참조하는 경우 프로그램이 예기치 않게 작동합니다.

+0

문제는'vector :: erase()'에 관한 것이지'delete'가 아닙니다. 동작은 아직 정의되지 않았지만 유효하지 않은 메모리 위치가 아닌 잘못된 개체에 액세스하고 있기 때문에 발생합니다. –

+2

내부적으로'vector :: erase()'는 저장된 객체에서'delete'를 호출 할 것이므로 같은 이유로 인해 정의되지 않은 동작입니다. 'delete'는 객체가 유효하지 않은 이유입니다. –

0

벡터가 메모리를 해제하지 않았지만 나중에 사용할 수 있도록 유지했습니다.

이것은 "정의되지 않은 동작"이라고합니다. 다음에 작동하고 나중에 시도 할 때 프로그램이 쉽게 중단 될 수 있다는 보장이 없습니다. 하지 마.

1

시작하려면 모든 시스템에서이 방법을 사용하지 마십시오. 내부적으로 벡터가 작동하는 방식은 입니다. 완전히 구현에 따라 다릅니다. 유효하지 않은 메모리 위치를 역 참조하면 문서에 설명 된 동작을 피할 수 있습니다. 즉, 의 동작 만 계산하면 STL 문서에 설명되어 있습니다.

여전히 메모리 위치에 액세스 할 수있는 이유는 사용중인 특정 구현이 메모리를 즉시 삭제하지는 않지만 성능상의 이유로 잠시 동안 계속 유지하기 때문입니다. 저자가 원한다면 또 다른 구현은 메모리를 즉시 삭제할 수 있습니다.

0

컴파일러 옵션은 무엇입니까? 보통의 컴파일러 (g ++ 및 VC++)를 사용하여 일반적인 옵션으로 충돌이 발생합니다. g ++의 경우,이 동작을 위해 추가로 옵션을 설정해야합니다 (-D_GLIBCXX_DEBUG, 제 생각 엔). 까지 내가 말할 수있는, 그것은 VC의 기본입니다 + +. (VC++에 대한 나의 명령 그냥 "CL/환경 안전 bounds.cc"이었다.)

다른 사람들이 말했듯이

, 그것은 정의되지 않은 동작은하지만 좋은 컴파일러로,이 충돌하는 프로그램을 일으킬 정의됩니다.

+0

옵션 없음, 단지 g ++ a.cpp -o a ... 아마 -O4. 그게 아무것도 바꿀 수 있다고 생각하니? – Shawn

+0

g ++ (그리고 내가 사용 해본 모든 다른 컴파일러)에는 심각한 일을하기 위해 여러 옵션이 필요합니다. 성능에 너무 많은 영향을주지 않는 한, 예를 들어 -D_GLIBCXX_DEBUG를 강력히 추천합니다. –