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

C++ 기초 : 클래스 (3)

글: 시플마 2024. 4. 13.

int i = 0;
int i2 = 10;

i = i2;

 

위와 같은 코드가 있습니다.

 

변수 i에 변수 i2의 값을 복사하여 넣겠다는 거죠.

 

이것을 '대입'이라고 합니다.

 

 

그럼 아래와 같은 코드는 어떤가요?

 

cMy형 객체 c에 cMy형 객체 c2의 값을 대입하였습니다.

 

 

오류도 발생하지 않고 

 

c2의 멤버 m_i의 값이 c의 멤버 m_i에

복사된 것이 보입니다.

 

 

대입을 했을 뿐인데 알아서

객체 c2의 멤버 변수의 값이

객체 c의 멤버 변수에 대입되었습니다.

 

어떻게 이런 일이 가능할까요?

 

 

아래 코드에서

 

14 ~ 19번째 줄을 보면

대입 연산자라는 것이 있습니다.

 

대입 연산자는 따로 만들어 주지 않아도 

대입 연산이 발생할 수 있기 때문에

컴파일러가 알아서 만들어서 실행해 주는 함수입니다.

 

대입 연산 외 +나 - 등 다른 연산은 자동으로

만들어 주지 않기 때문에 객체끼리

해당 연산을 적용하고 싶다면  직접 만들어 줘야 합니다.

 

 


 

 

 

 

그럼 자동으로 생성되는 대입 연산자에 대해 

자세히 알아보기 전에 '&'의 의미부터 알아보죠.

 

C++에서는 레퍼런스(참조)라는 개념이 생겼습니다.

 

아래와 같은 코드가 있을 때

 

iRef가 바로 레퍼런스 변수입니다.

 

iRef에 i를 넣은 후(참조한 후)

iRef의 값을 100으로 바꾸면 i의 값이 100으로 바뀝니다.

 

 

위 과정을 포인터로 표현하면

 

위와 같습니다.

 

 

둘의 차이점은

레퍼런스 변수는 i를 바로 참조하기 때문에

레퍼런스 변수에 값을 대입한다는 것은, 

곧 변수 i에 값을 대입한다는 것과 같습니다.

 

반면

포인터 변수는 변수 i의 주솟값을 저장하기 때문에

역참조(*)를 통해서 해당 주솟값으로 이동한 후,

변수 i에 값을 대입하죠.

 

역참조를 통해서 값에 접근하는 포인터와 달리

레퍼런스는 바로 변수의 값으로 접근할 수 있다는

점으로 인해 레퍼런스 변수만이 할 수 있는 것이 있습니다.

 

 

그리고 실제 컴파일된 코드는 같지만 

포인터 변수는 주솟값을 받는 형태이기 때문에

주소 연산을 잘못하면 의도하지 않은 메모리에 

접근할 수도 있지만, 레퍼런스 변수는 그렇지 않기 때문에

사용자가 주소와 관련하여 실수할 여지가 없습니다.

 

 

또한 레퍼런스 변수는 특정 변수를

참조하는 순간 다른 변수를 참조할 수 없습니다.

 

포인터로 표현하면

 

포인터 변수명 바로 앞에 const가 

붙는 경우와 같다고 할 수 있습니다.

 

포인터 변수 p는 const가 포인터 변수명

앞에 붙었기 때문에 변수 i의 주솟값 외의 

다른 변수의 주솟값은 받을 수 없죠.

 

레퍼런스 변수는 기본적으로 어떤 변수를

참조하면 다른 변수를 참조할 수 없는 구조입니다.

 

 

레퍼런스 변수에도 const 키워드를 붙여

 

참조하고 있는 변수의 값을

수정하지 못하게 막을 수 있습니다.

 

이를 포인터 변수로 나타내면 자료형 앞과

변수명 뒤에 const를 붙인 형태와 같다고 볼 수 있네요.

 

 


 

 

 

이제 클래스 cMy를 다시 보겠습니다.

 

대입 연산자는 마치 함수처럼 작동하는 것입니다.

 

'=' 연산이 발생하면 해당 연산자가 실행되는 거죠.

 

만약 '+' 연산과 관련하여 만들고 싶다고 하면

operator +의 형태로 작성해 주면 되겠죠.

 

 

근데 일반 변수에도 '=' 연산(대입 연산)을 할 수 있죠?

이러면 이름이 겹치는 거 아닌가라는 생각이 듭니다.

 

그러나 함수 이름이 같아도 매개 변수나 반환 타입이 다른 경우

함수 오버로딩으로 인해 문제가 발생하지 않았죠.

 

마찬가지로 연산자도 오버로딩이 가능하기 때문에

문제가 발생하지 않습니다.

 

 

일단 매개 변수부터 살펴 봅시다.

 

받은 인자를 레퍼런스 변수로 참조합니다.

근데 const가 붙었으므로 받은 cMy형 객체를

참조는 하나 값을 바꾸지 않겠다는 의미이죠.

 

이후 자신의 멤버 m_i에

인자로 받은 객체의 멤버 m_i의 값을 대입합니다.

 

아래와 같은 상황이라면

 

this->m_i는 객체 c의 멤버일 것이고,

_Other.m_i는 객치 c2의 멤버겠죠.

 

그리고 this 포인터를 역참조하여 값을 반환하는데

this 포인터가 저장하고 있는 것은 객체 c의 주솟값이고

이를 역참조하여 이동하면 객체 c가 있겠죠.

이 값을 cMy형 레퍼런스 형태로 반환합니다.

 

 

여기서 cMy형 레퍼런스 형태로 반환하는 이유는

 

위와 같은 코드가 있다고 했을 때

c3의 멤버 변수의 값이 c2의 멤버 변수의 값으로 복사가 될 겁니다.

 

그럼 c = c2; 가 될 것이고 

복사된 c2의 멤버 변수의 값이 c의 멤버 변수의 값으로 복사가 될 겁니다.

 

근데 = 연산자의 반환값이 없으면 

 

마치 위와 같은 상황이 되는 겁니다.

 

c3와 c2의 대입 연산 이후, 반환값이 없으니 

c에 대입할 어떤 값이 존재하지 않는 것이죠.

 

그래서 c3를 c2에 대입한 이후, 

c2의 주솟값이 저장된 this 포인터를 

역참조하여 실제 객체 c2에 접근하고 

이를 참조할 수 있도록 cMy형 레퍼런스로 

반환하는 겁니다.

 

 

 

 

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


 

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

C++ 기초 : 함수 템플릿  (0) 2024.04.17
C++ 기초 : 클래스를 이용한 배열  (0) 2024.04.14
C++ 기초 : 클래스 (2)  (0) 2024.04.13
C++ 기초 : 클래스 (1)  (0) 2024.04.13
C++ 기초 : 리스트 (3)  (0) 2024.04.12