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

C++ 기초 : iterator (5)

글: 시플마 2024. 4. 22.

후위 ++ 연산자를 오버로딩하겠습니다.

 

후위처럼 작동하게 하려면

우선 함수 내에 지역 변수를 하나 만들어야 합니다.

 

iterator형 지역 변수를 하나 만든 후,

해당 연산자를 호출한 iterator의 값을 통해 초기화합니다.

 

해당 연산자를 호출한 iterator의 값을 하나 올린 후

지역 변수를 반환합니다.

 

이렇게 되면 연산자는 iterator의 값을 올리기 전에 반환하고

연산자를 호출한 iterator는 다음 데이터를 가리키게 되겠죠.

 

 

실행 결과를 보니

 

a1에는 myiter가 가리키고 있던 공간의 값을 저장한 후

myiter에 ++ 연산이 진행되면서

a2에는 myiter가 가리키던 공간으로부터 다음 공간의 값을

저장하고 있음을 확인할 수 있습니다.

 

 

 


 

 

 

 

이제 -- 연산자도 오버로딩해 보겠습니다.

 

전위부터 처리하도록 합시다.

 

++ 연산자와 거의 같습니다.

 

다른 점은 83, 88번째 줄입니다.

 

iterator가 가변 배열의 가장 처음을 가리키고 있는 상태에서

-- 연산을 하면 안되기 때문에 인덱스를 나타내는

idx의 값이 0일 때는 idx에 -1을 대입하여 예외 처리가 

발생할 수 있도록 합니다.

 

두 if 문에 걸리지 않는다면 idx의 값을 하나 내리도록 합니다.

 

 

아래 실행 결과를 보시면

 

10이 들어가 있는 공간을 가리키는

myiter에 ++ 연산을 하여 20이 있는 공간을 가리키게 한 후

-- 연산을 하여 다시 10이 있는 공간을 가리키게 하였습니다.

 

그리고 역참조하여 값을 얻은 후 a1에 대입하고

값을 확인해 보니 정말 10이 대입된 것을 볼 수 있네요.

 

 

후위 -- 연산자의 경우

 

++ 부분이 --이 되었다는 것 말고 다른 점은 없습니다.

 

 

 


 

 

 

 

클래스를 만들면 코드 작성자가 직접 입력하지 않아도

자동으로 생성되는 함수가 몇 개 있었습니다.

 

기본 생성자와 기본 소멸자가 대표적이죠.

 

 

또한 대입 연산자(=)도 자동으로 만들어 줍니다.

 

대입 연산자를 따로 만들어 주지 않아도 위 코드와 같은

대입 연산자가 오버로딩됩니다.

 

덕분에 두 객체가 서로 다르더라도 같은 클래스로 만든 객체라면

대입 연산이 가능한 거죠. 좌항의 멤버 변수에

우항의 멤버 변수의 값이 대입이 되죠.

 

우항에 있는 객체는 값이 변할 필요가 없고 참조를 통해

복사를 하지 않고 바로 값을 대입하기 위해 const 레퍼런스로 받습니다.

 

CTest t1, t2, t3;

t1 = t2 = t3;

 

위 코드처럼 연달아서 대입 연산할 수도 있으므로

자기 자신을 반환하며 반환 타입도 레퍼런스로 하여

바로 값을 참조하여 대입할 수 있도록 합니다.

 

 

 


 

 

 

 

복사 생성자라는 것도 자동으로 만들어집니다.

 

30번째 줄에 있는 것이 바로 복사 생성자입니다.

 

대입 연산자와 같아 보이지만 생성자이기 때문에 

이니셜라이저가 가능합니다. 참조한 다른 객체의 값을 통해

바로 초기화를 하는 것이죠.

 

 

근데 복사 생성자를 직접 작성하니 39번째 줄에 있는

객체 생성 부분이 오류가 납니다.

 

이유는 생성자를 하나라도 직접 구현하면

기본 생성자가 생성되지 않기 때문입니다.

 

기본 생성자는 만들어 주지 않으면

자동으로 만들어 주는 것이 아니라

아무런 생성자도 없으면 기본 생성자를 만들어 주는 것입니다.

 

위 코드 같은 경우 복사 생성자 역할을 하는

생성자를 하나 만들어 줬으니 기본 생성자가 

생성되지 않았고 이로 인해 아무 인자도 받지 않는

생성자를 찾을 수 없어 39번째 줄에서 오류가 발생하는 것이죠.

 

아래처럼

 

기본 생성자를 만들어 주면 오류가 사라집니다.

 

 

아래 코드에서

 

42 ~ 43번째 줄은 어떤 상황일까요?

 

42번째 줄에서 기본 생성자를 통해 객체가 만들어졌습니다.

이후 t1에 t2를 대입하고 있죠. 대입 연산자가 호출됐을 겁니다.

 

 

그럼 45번째 줄은 어떤가요?

 

t3에 t2가 대입된 것처럼 보여 대입 연산자가

호출되었을 거 같지만 그렇지 않습니다.

 

객체 t3가 만들어진 후 t2가 대입된 것이 아닌,

t3가 만들어지면서 t2를 통해 초기화한 것입니다.

 

즉 컴파일러가 알아서

CTest t3(t2)로 바꾸고

복사 생성자를 호출하는 것이죠.

 

 

47번째 줄도 마찬가지입니다.

 

복사 생성자를 호출하여

객체 t4를 생성하면서 t2를 통해 초기화하는 것이죠.

 

 

후위 ++ 연산자를 오버로딩한 코드를 보시면

 

69번째 줄의 코드는 대입 연산처럼 보이지만

사실은 자동으로 생성된 복사 생성자로 인해 

iterLocal이라는 객체의 멤버들이 this 멤버의 값들로

초기화되는 코드인 겁니다.

 

 

전위 연산이나 후위 연산이나 상관이 없을 때는

전위 연산을 사용하는 게 좋습니다. 

 

전위 연산은 지역 변수도 만들지 않고

반환 타입도 레퍼런스이므로 복사가 발생하지 않습니다.

 

하지만 후위 연산은 지역 변수를 만들고

초기화하는 과정에서 복사 생성자를 호출하여 

복사가 일어납니다. 반환 타입도 레퍼런스가 아니기 때문에 

함수가 종료되면서 iterLocal은 사라집니다.

이때 iterLocal의 값을 보존하기 위해 또 복사가 발생합니다.

 

 

 

 

 

 

 

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


 

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

C++ 기초 : erase (2)  (0) 2024.04.24
C++ 기초 : erase (1)  (0) 2024.04.24
C++ 기초 : iterator (4)  (0) 2024.04.22
C++ 기초 : iterator (3)  (0) 2024.04.22
C++ 기초 : iterator (2)  (0) 2024.04.20