Qaupot Blog
Software Engineering, Trip

204. this 포인터

🕐 Wed, 19 Feb 2014 09:00:00 GMT 🕓 Thu, 26 Aug 2021 13:18:00 GMT

this 포인터

this 포인터는 현재 멤버 함수가 호출된 인스턴스의 메모리 주소를 가르킵니다.

#include <iostream>

int val = 1;
class Number
{
private:
    int val = 0;
public:
    void add(int val)
    {
        this->val += val;
    }
    int getVal() { return this->val; }
};

int main(int argc, char** argv)
{
    Number num;
    num.add(3);

    printf("%d\n", num.getVal());
    return 0;
}

위 Number 클래스에서의 this 는 Number 형의 포인터가 됩니다.

멤버 함수내에서 명칭의 우선순위는 "지역변수 > 멤버변수 > 전역변수" 순입니다.

add 함수의 인수 val 는 지역변수 취급이 되므로 멤버변수 val 보다 우선순위가 높기 때문에, this 포인터를 이용해서 명시적으로 멤버 변수 val 에 지역변수 val 를 대입하고 있습니다.

void add(int val)
{
    val += val;
}

만약 위의 add 함수를 위와 같이 고치면, 출력되는 값은 3이 아닌 0이 됩니다.

지역 변수 val 에 지역 변수 val 을 더했기 때문에 멤버의 val 는 변동이 없고, 지역 변수는 함수가 끝남과 동시에 사라집니다.

this 포인터는 왜 존재하는가?

this 포인터는 C++의 클래스의 동작 중 멤버 변수들과 멤버 함수들을 연결해 주는 역할을 합니다.

변수들은 저장 공간인 메모리를 의미하고, 함수들은 실행 루틴을 의미합니다.

  • 변수들은 각각의 인스턴스에서 보관할 내역이 다르기 때문에 별도로 존재해야 합니다.
  • 실행 루틴은 인스턴스가 아무리 늘어나더라도, 모두 동일합니다.

인스턴스별로 루틴을 가지고 있는 것은 비효율적입니다.

프로세스의 구조 상 변수 혹은 상수들이 보관되는 영역과 (스택, 힙, 데이터) 실행 루틴이 존재하는 영역(코드)은 나뉘어 있습니다.
코드 영역은 실행 중의 루틴 변경을 막기 위해 보호되어 런타임 중에 변경할 수 없습니다.

인스턴스는 독자적인 멤버 변수들을 가지지만 클래스 공통의 멤버 함수와 매칭됩니다.

멤버 함수가 인스턴스를 구별하는 방법이 this 포인터이며, 멤버 함수의 호출 시점에, 호출한 인스턴스의 포인터를 같이 보냅니다.
이후 멤버 함수는 인스턴스의 포인터 (this 포인터)를 가지고 멤버 변수들에 접근합니다.

void add(Number* this, int val)
{
  this->val += val;
}

실질적, add 멤버 함수의 코드는 위와 같다고 볼 수 있습니다.

Exercise

golang 을 비롯한 functional language 는 receiver 라는 개념이 있습니다. 기회가 되신다면, this 와 사용법을 비교해 보세요.

이 블로그는 개인 블로그입니다. 게시글은 오류를 포함하고 있을 수 있지만, 저자는 오류를 해결하기 위해 노력하고 있습니다.
게시글에 별도의 고지가 없는 경우, 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 라이선스를 따릅니다.

This blog is personal blog. published posts may contain some errors, but author doing efforts to clear errors.
If post have not notice of license, it under creative commons Attribution-NonCommercial-NoDerivatives 4.0.