스마트 포인터 개념.

보물창고·2022년 8월 25일
0

c++ basic 코드누리

목록 보기
44/50

problem

가) Car 클래스를 만들고, Ptr객체에 포인터 형식으로 넣어서,
생성자에서 할당, 소멸자에서 해제하라.
나) Car를 외부에서 동적할당 하고, 해제 코드는 작성하지 마라.

problem

밑의 코드가 가능하게 포인터 클래스와, Car 클래스를 만들어라.
Ptr p = new Car;
p->Go();
(*p).Go();

  • 일단 코드에 이렇게 작성한 다음에, operator 연산자를 어떻게 만들지 생각해보면, 만들 수 있음.

개념

: 객체이지만, 포인터처럼 동작하는 객체

만드는 방법.

  1. 객체 내부에 다른 클래스의 포인터객체 를 가지고 있음.
  2. 생성자에서 인자로 들어오는 포인터를 받도록 하자.
    1. 포인터처럼 동작하게 하기 위해서 ->, 를 만들어야 함.
      (
      * )포인터 연산자의 경우, 반환값은 복사 방지를 위해 참조반환 해야 함.

헷갈림

  1. " * " : 변수의 주소이므로, operator() 반환값은 역참조
    -> 이때 주소값은 또 복사될 수 있으니까 참조로
  2. -> : -> 는 포인터 자체이므로 반환값은 포인터 변수

예시 코드

: Car를 포인터가 아닌 객체로 선언했지만, 포인터와 동일하게 new 하면서 초기화 하고 있음.

#include <iostream>

class Car
{
public:
	void Go() { std::cout << "Go"   << std::endl; }
	~Car()    { std::cout << "~Car" << std::endl; }
};

class SPtr
{
	Car* ptr;
public:
	SPtr(Car* p = 0) : ptr(p) {}
	
	~SPtr() { delete ptr; }

	Car* operator->() { return ptr; }
	Car& operator*()  { return *ptr; }
};

int main()
{
	// SPtr의 객체 p가 Car의 포인터 처럼 사용
	// Car* p = new Car;
	SPtr p = new Car; // SPtr p( new Car )

	p->Go(); // p + a : p.operator+(a)
			 // (p.operator->())Go()         
			 // (p.operator->())->Go()  

	(*p).Go(); // p.operator*()
}

특징

'-> 연산자' 와, '. 연산자' 를 이용해 객체 내부에 있는
포인터 객체에 접근할 수 있게 해야 함.

장점.

  • 포인터가 아닌 객체이므로, 반드시 스코프를 벗어나면 소멸자가 호출되므로.
    클래스 내에 해제할 수 있음.

    실제 포인터 객체를 쓸 경우, 객체가 아니라서,
    클래스 외부에서 유저가 관리해야 함.

  • 생성 / 복사 / 대입 / 파괴의 모든 과정에서 원하는 작업을 수행할 수 있음.

profile
🔥🔥🔥

0개의 댓글