상세 컨텐츠

본문 제목

C++ this

C++/C++98

by deulee 2023. 8. 5. 11:56

본문

this

다시 한번 복기해보도록 하자.

 

멤버 변수는 객체별로 따로 메모리가 할당되고 멤버 함수는 클래스에 속하는 모든 객체들이 하나의 메모리를 공유하는것을 알고 있을 것이다.

 

그러면 다음 코드를 보도록 하자.

 

#include <iostream>

class Thing
{
private:
	int num;
public:
	Thing(int n) : num(n)
	{}
	void OutValue()
	{
		std::cout << num << std::endl;
	}
};

int main(void)
{
	Thing A(3);
	Thing B(5);
	A.OutValue();
	B.OutValue();
	return 0;
}

이 코드의 결과물은 당연하게도 3, 5가 차례대로 출력될 것이다.

 

그럼 의문을 하나 가져보도록 하자.

 

멤버 함수인 OutValue는 인스턴스 A, B 모두 공유하게 될 텐데 이 함수는 어떻게 각 인스턴스를 구분하고 해당 객체의 값을 출력했을까? 특별히 다른 인수를 넘긴것도 아닌데 말이다.

 

결론부터 말하자면 다음과 같다.

 

OutValue 함수를 호출할 때 어떤 객체 소속의 멤버 함수를 호출할 것인지 즉, 소속 객체를 함수 이름 앞에 밝혔기 때문이다.

 

하지만 여전히 함수 입장에서는 알 방법이 없다.

 

그렇기 때문에 컴파일러는 멤버 함수가 호출한 객체를 구분하기 위해서 호출문의 객체를 함수의 인수로 암시적으로 전달한다. 즉, 위의 호출 문구는 다음으로 재해석 된다.

A.OutValue() -> OutValue(&A) // 객체의 메모리 주소가 전달되는 것을 보자.

이때 전달받은 숨겨진 인수를 this라고 부르며 호출한 객체의 번지를 가리키는 포인터 상수이다. 그럼 컴파일러에 의해 재해석된 함수 정의부를 다시 보도록 하자.

void OutValue(Thing* const this)
{
	std::cout << this->num << std::endl;
}

그렇기 때문에 사실은 this가 하나 더 전달 되기 때문에 항상 N + 1 개의 인수가 전달된다고 생각하면 된다.

 

이렇게 멤버 함수 호출시에 this를 암시적으로 전달하는 호출 규약을 thiscall이라고 하는데 모든 멤버 함수에 자동으로 적용된다. 단, 가변 인수를 취하는 멤버 함수는 cdecl 호출 규약을 사용한다.

 

함수 호출 규약에 대해 궁금하다면 다음 글을 보자.

 

https://over-stack.tistory.com/23

 

C/C++ 함수의 호출 규약 (Calling Convention) with 어셈블리

안녕하세요, IT디자이너입니다. 이번 포스팅은 함수 호출 규약에 관하여 설명드리도록 하겠습니다. 소개해드릴 함수 호출 규약은 cdecl,stdcall,fastcall 입니다. 이 함수 호출 규약 말고도 여러가지의

over-stack.tistory.com

 

this는 어떤 상황에서 사용할 수 있을까?

 

1. 자기 자신을 리턴해야 할 경우

// 포인터를 보낼 경우
Thing* getBigger(Thing* Other)
{
	if (Other->num > num)
		return Other;
	else
		return this;
}

// 레퍼런스를 보낼 경우
Thing& getBigger(Thing& Other)
{
	if (Other.num > num)
		return Other;
	else
		return *this;
}

A.getBigger(&B)->OutValue(); // call by address

A.getBigger(B).OutValue(); // call by reference

 

위와 같이 자기 자신을 리턴하거나 인수로 넘길 때 사용이 가능하다.

 

2. 자기 자신을 죽일 경우

 

프로그램이 오류가 발생해서 스스로를 삭제하고자 할때 다음과 같이 사용할 수도 있다.

delete this;

 

3. 네임 충돌을 방지하고자 할 경우

 

이 전의 코드들을 보면 이름이 같은 경우가 있다. 이런 경우 네이밍 충돌이나 혼동을 막기 위해 this를 사용하는 경우가 자주 있다.

if (Other->num > this->Num)

class Some
{
private:
	int i;
public:
	void func()
	{
		int i;
		this->i = 3; // 객체의 멤버 변수를 지정
	}
}

 

출처

http://www.soen.kr/lecture/ccpp/cpplec.htm

 

C/C++ 강좌

 

www.soen.kr

 

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

C++ 상수 멤버, const  (0) 2023.08.05
C++ 정적 멤버, static  (0) 2023.08.05
C++ 프렌드  (0) 2023.08.05
C++ 생성자, 파괴자, 복사 생성자, 복사 대입 연산자  (0) 2023.08.03
C++ 함수 오버로딩  (0) 2023.08.03

관련글 더보기