본문 바로가기
C++/기초

C++ 기초 : erase (1)

글: 시플마 2024. 4. 24.

이제 erase 함수를 구현해 볼 건데

erase 함수가 어떤 역할을 하는지 알아야겠죠?

 

아래 코드를 보시면

 

표준 라이브러리에서 제공하는 vector를 통해 

가변 배열을 만들었고 해당 가변 배열에는 10과 20이 

차례대로 들어 있습니다.

 

그리고 10이 있는 공간을 iteraor를 통해

가리키고 있죠.

 

vector의 멤버 함수 erase를 통해

iterator가 가리키는 공간을 제거합니다.

즉 첫 번째 공간을 제거하는 것이죠.

 

가변 배열은 중간에 빈 공간을 두면

안됩니다. 그래서 첫 번째 공간을 다음 데이터가 메꾸게 되죠.

 

위 같은 경우에는 10이 제거되어 첫 번째 공간을

20으로 메꾸게 되겠죠.

 

 

그러면 iterator는 자연스럽게 20을 가리키게 되겠고

iterator를 역참조하면 20이라는 값이 반환될 겁니다.

 

이 값을 다시 변수 data에 대입하겠습니다.

 

실행해 보니

 

오류가 발생합니다. 

 

왜 오류가 발생할까요?

 

vector에서 제거된 공간을 다음 데이터가 메꿨다고 해도,

iterator가 제거된 공간을 가리키고 있으므로

iterator가 적절하지 않은 곳을 가리키고 있다고

인지하여 오류 창을 띄우는 것이죠.

 

 

그래서 아래 코드에서

 

21번째 줄처럼 iterator가 가리키는 공간을

제거한 후에, 뒤의 데이터가 앞의 공간을 메꾸면

이를 다시 iterator에 대입한 후

역참조해야 정상적으로 작동하죠.

 

변수 data에 20이 잘 대입되었네요.

 

 

이번에는 가변 배열 맨 뒤에

 

30이라는 값을 넣었습니다.

 

그리고 iterator가 처음을 가리키게 합니다.

이후 erase 함수를 통해 iterator를

++ 연산한 후 해당 공간을 제거했습니다. 

 

++ 연산(전위)을 하였으니 처음을 가리키던

iterator가 20이 있는 공간을 가리키게 되고

그 공간을 제거하게 됩니다. 그러면 30으로 메꿔지겠죠.

 

그래서 iterator는 결국 30을 가리키게 되므로

변수 data에 30이 대입되는 것이죠.

 

 


 

 

erase 함수를 호출하는 vector 입장에서는

iterator가 어떤 공간을 가리키는지 알 수 있어야

iterator가 가리키는 그 공간을 제거할 수 있겠죠.

 

즉 iterator의 멤버에 접근할 수 있어야 할 겁니다.

 

 

inner 클래스인 iterator는 vector의 private으로 선언된

멤버에 접근할 수 있지만, vector는 inner 클래스인 iterator의

private으로 선언된 멤버에 접근할 수 없습니다.

 

이것을 가능하게 하는 것은 멤버 변수를 public으로 선언하거나,

멤버 변수의 값을 반환하는 함수를 따로 만들거나,

friend 키워드를 사용하면 됩니다.

 

아래 코드는

 

inner 클래스인 iterator의 마지막 부분입니다.

 

137번째 줄을 보시면 

friend class cArr; 이라는 코드가 보이시죠?

 

이를 통해 가변 배열을 구현하기 위한 클래스 cArr이

inner 클래스인 iterator의 멤버 변수에 접근할 수 있게 됩니다.

 

중요한 건 멤버를 공개하는 클래스 쪽에서

friend 선언을 해 줘야 하는 것입니다.

 

반대로 cArr 클래스 마지막 부분에

friend class iterator; 를 작성하는 게 아닙니다.

 

 

 


 

 

 

본격적으로 erase 함수를 구현하겠습니다.

 

cArr 클래스에 선언을 하고 

클래스 밖에 erase 함수를 정의하겠습니다.

 

마찬가지로 cArr 클래스 템플릿을 통해 객체를

만들기 때문에 해당 멤버 함수도 템플릿으로 구성해야 하죠.

 

cArr<T> 클래스 안에 있는 iterator라는 클래스를 반환 타입으로 하며

cArr<T> 클래스의 멤버 함수이므로 범위 지정 연산자(::)를 통해

위 코드처럼 명시해 줘야 합니다. 

템플릿을 구성하는 시점에 어떤 자료형이

들어올지 미리 알 수 없습니다.

그래서 임의의 문자를 정해(여기서는 대문자 T)

typename T과 같이 적었었죠. T 자리에 

각종 자료형이 들어오면서 클래스 템플릿을 통해

클래스가 만들어집니다.

 

 

반환 타입 앞에 typename을 적는 이유는

typename 키워드를 붙이지 않으면

컴파일러는 반환 타입 iterator가 뭔지 모르기 때문에 

iterator라는 형식이 있음을 알려주기 위해 붙이는 겁니다.

 

 

erase 함수는 iterator가 가리키는 공간을

제거하는 함수이므로 어딘가를 가리키는 이 iterator를

인자로 받습니다. vector가 관리하는 가변 배열을 제거하는 것이지

이정표 역할을 하는 iterator의 값은 바꿀 필요가 없고,

값을 참조하면 복사하는 비용을

아낄 수 있으므로 const iterator형 레퍼런스로 받습니다.

 

 

226번째 줄에서 if 문의 의미는, 아래 그림을 보시면

 

vector를 통해 erase 함수를 호출하였을 때 

vector2의 공간을 가리키는 iterator를 인자로 받으면

안되겠죠? 그렇기 때문에 if 문이 있는 겁니다.

 

vector의 공간을 제거하는데

vector2의 공간을 가리키는 iterator를 인자로 받아

erase 함수를 실행하면 vector2의 공간이 제거되는

문제가 발생합니다.

 

이러한 문제를 방지하기 위해

this(erase 함수를 호출한 vector)와 

iterator가 가리키는 vector가 다르면 오류 창을 출력합니다.

 

실제 vector를 통해 확인해 보죠.

 

realvector2로 erase 함수를 호출하여

realvector의 공간을 가리키고 있는

iterator를 인자로 넘기면

오류 창이 뜨는 것을 확인할 수 있습니다.

 

 

또는 iterator가 end를 가리키고 있다면 오류 창을 출력합니다.

end 함수를 먼저 구현했고 == 연산자도 오버로딩했으므로

이러한 구문이 가능합니다.

 

 

 

 

강의 출처 : https://www.youtube.com/watch?v=PFc4g8mxOiI&list=PL4SIC1d_ab-aOxWPucn31NHkQvNPHK1D1&pp=iAQB


'C++ > 기초' 카테고리의 다른 글

C++ 기초 : list iterator  (0) 2024.04.25
C++ 기초 : erase (2)  (0) 2024.04.24
C++ 기초 : iterator (5)  (0) 2024.04.22
C++ 기초 : iterator (4)  (0) 2024.04.22
C++ 기초 : iterator (3)  (0) 2024.04.22