TIL 2024/8/12

Sung Joo Lee·2024년 8월 12일

this 포인터


  • this는 CPP 키워드

  • 현재 객체 자신을 가리키는 포인터

    • 코드에서 해당 메소드를 호출한 객체의 주소 값이 할당 되어있다는 것을 알면 된다.
  • 객체가 생성될 때 마다 해당 객체에 대한 메모리 주소가 할당되며, 이 주소가 this 포인터에 저장된다.

  • 사용 예

#include <iostream>

class Player {
private:
	int x, y;
public:
	Player(int x, int y);
	void setPosition(int x, int y);
	void printPos();
};

int main()
{
	Player p1{ 0,0 };
	p1.setPosition(10, 10);

	p1.printPos();
	return 0;
}

Player::Player(int x, int y)
	:x{x},y{y}
{}

void Player::printPos() {
	std::cout<< "X: " << this->x <<std::endl;
	std::cout << "Y: " << this->y << std::endl;
}

void Player::setPosition(int x, int y) {//명확하지 않다
	x = x;
	y = y;
}

결과

  • 결과를 보면 10,10으로 초기화가 되어있지 않은 것을 볼 수 있는데 이는 명확하지 않기 때문이다.

명확하지 않다?

setPosition의 매개변수 x , y 와 Player class가 가지고 있는 x,y가 이름이 같기 때문이다.
컴파일러가 x,y가 어떤 x,y인지 구분을 하지 못 하기 때문이다.

그럼 진짜 이름 때문에 그런 것인지 확인해 보자

#include <iostream>

class Player {
private:
	int x, y;
public:
	Player(int x, int y);
	void setPosition(int x, int y);
	void printPos();
};

int main()
{
	Player p1{ 0,0 };
	p1.setPosition(10, 10);

	p1.printPos();
	return 0;
}

Player::Player(int x, int y)
	:x{x},y{y}
{}

void Player::printPos() {
	std::cout<< "X: " << this->x <<std::endl;
	std::cout << "Y: " << this->y << std::endl;
}

void Player::setPosition(int xPos, int yPos) {
	x = xPos;
	y = yPos;
}

결과

  • 실제로 xPos,yPos로 매개변수 이름을 바꾸니 값이 제대로 들어가 있는 것을 확인했다.

해결해보기

  • this pointer를 사용한다.

  • this는 p1 객체가 선언 되었을 때 메모리에 생성된다.

  • this를 사용하여 p1객체의 x,y에 매개변ㅅ후 x,y의 값을 할당 해 준다.

#include <iostream>

class Player {
private:
	int x, y;
public:
	Player(int x, int y);
	void setPosition(int x, int y);
	void printPos();
};

int main()
{
	Player p1{ 0,0 };
	p1.setPosition(10, 10);

	p1.printPos();
	return 0;
}

Player::Player(int x, int y)
	:x{ x }, y{ y }
{}

void Player::printPos() {
	std::cout << "X: " << this->x << std::endl;
	std::cout << "Y: " << this->y << std::endl;
}

void Player::setPosition(int x, int y) {//명확하지 않다
	this->x = x;
	this->y = y;
}

Const 객체


  • Const-correctness
  • Const 객체의 멤버 변수의 값은 변경 불가능
#include <iostream>

class Player {
private:
	int x, y;
	int speed;
public:
	Player(int x, int y, int speed)
		:x{ x }, y{ y }, speed{ speed }
	{
		std::cout << this << std::endl;
	}

	void setPosition(int x, int y)
	{
		this->x = x;
		this->y = y;
	}

	void printPosition()
	{
		std::cout << x << "," << y << std::endl;
	}
};

int main()
{
	const Player p1{ 1,1,1,};//cosnt로 선언하면 멤버 변수의 값을 수정 할 수 없다.
	p1.printPosition();///ERR
	
	p1.setPosition(10,10);//ERR

	p1.printPosition();//ERR

	return 0;
}

객체 p 를 const로 선언했기 때문에 멤버 변수의 값을 수정 불가능

근데 setPosition은 this로 값을 변경하지만 printPosition은 값을 변경하지 않는데도 호출이 불가능하다.

why?

  • 컴파일러가 해당 함수의 본문 안에서 값을 바꿀지 바꾸지 않을지 알 수 가 없다.

  • 컴파일러에게 함수 뒤에 const를 붙여서 해당 함수는 값을 변경하지 않는다는 것을 알려줘야 한다.

예시)

	void printPosition() const
	{
		std::cout << x << "," << y << std::endl;
	}
  • 위와 같이 const를 명시적으로 알려주면 호출이 가능하다.

의문

  • 여기서 compiler가 해당 함수에 코드를 보면 해당 함수가 값을 변경하는지 안하는지 충분히 알 수 있을텐데 왜 const로 명시 해줘야 할까?라는 생각을 했다.

const를 명시하지 않으면 안 되는 이유

컴파일러가 자동으로 코드가 객체의 상태를 변경하는지 판단할 수 있을 것 같지만, C++에서는 개발자의 의도를 명확하게 나타내는 것을 중요시합니다. 만약 컴파일러가 함수가 상태를 변경하는지 아닌지를 판단하게 한다면, 다음과 같은 문제가 발생할 수 있습니다.

  • 의도와 구현의 불일치: 개발자는 특정 함수가 객체의 상태를 변경하지 않도록 작성했다고 생각할 수 있지만, 실수로 상태를 변경하는 코드가 포함될 수 있습니다. const가 없다면 이러한 실수를 컴파일러가 잡아주지 못할 수 있습니다.
  • 미래의 코드 변경: 함수가 현재는 상태를 변경하지 않지만, 나중에 수정되면서 상태를 변경하게 될 수도 있습니다. 이때 const가 없다면, 이러한 변경이 무심코 const 객체에 적용될 수 있고, 이로 인해 예상치 못한 버그가 발생할 수 있습니다.
profile
개발로그

0개의 댓글