본문 바로가기

Cpp

스마트 포인터

포인터 변수를 통해 동적할당 했을 때에는 항상 해제를 해주어야한다.

그래서 c++ 에서 new를 배울 때는 delete 키워드를 같이 공부한다.

 

그런데 여러 경우에서 할당한 메모리를 해제하지 못하는 경우가 생긴다.

실수로 delete 를 넣지 않았을 때도 있고, 예외처리 과정에서의 delete 선언을 부분적으로하여

메모리 누수가 생기는 경우 등이 있다.

 

void remodel(std::string& str)
{
	std::string * ps = new std::string(str);

	str = *ps;

	// delete ps; // 실수로 주석처리를 해버렸다!
	return;
}
void remodel2(std::string& str)
{
	std::string* ps = new std::string(str);

	if (1)
	{
		throw ~~~~ // 예외처리에 의해 밑에 delete 구문이 실행되지 않았다!
	}

	str = *ps;

	delete ps;
	return;
}

이러한 실수에는 당연히 해결 방법들이 많이 있지만 스마트 포인터를 활용하여 간단하게 해결이 가능하다.

 

ps 객체가 클래스 였다면 파괴자 매커니즘을 통해 지시되는 메모리도 함께 해제가 될 수 있겠지만

일반 포인터라면 문제가 된다.

 

스마트 포인터 변수는 본인이 포함되어 있는 지역을 벗어나 스택 메모리로부터 삭제 될 때,

스마트 포인터가 가리키는 메모리도 함께 해제된다.

 

스마트 포인터는 auto_ptr, unique_ptr, shared_ptr 등이 있다.

스마트 포인터를 사용하기 위해서는 memory 헤더 파일을 추가해야한다.

스마트 포인터의 수명이 다하면 파괴자는 delete 를 사용하여 메모리를 해제한다.

그래서 나중에 메모리를 해제할 필요가 없고, 스마트 포인터가 삭제 될 때, 자동적으로 메모리가 해제된다.

 

다음은 스마트 포인터의 선언 및 파괴될 때 확인을 위한 짧은 스크립트이다.

#include <iostream>
#include <string>
#include <memory> // 스마트 포인터 사용을 위해 추가하는 헤더 파일

class Report
{
private:
	std::string str;
public:
	Report(const std::string s) : str(s)
	{
		std::cout << "객체가 생성되었습니다.!\n";
	}
	~Report() { std::cout << "객체가 삭제되었습니다!\n"; }
	void comment() const { std::cout << str << "\n"; }
};

int main(void)
{
	{
		std::auto_ptr<Report> ps(new Report("auto_ptr"));
		ps->comment();
	}
	{
		std::shared_ptr<Report> ps(new Report("shared_ptr"));
		ps->comment();
	}
	{
		std::unique_ptr<Report> ps(new Report("unique_ptr"));
		ps->comment();
	}
	return 0;
}
더보기

객체가 생성되었습니다.!
auto_ptr
객체가 삭제되었습니다!
객체가 생성되었습니다.!
shared_ptr
객체가 삭제되었습니다!
객체가 생성되었습니다.!
unique_ptr
객체가 삭제되었습니다!

스마트 포인터는 명시적 변환을 해주어야한다.

 

스마트 포인터는 가리키는 주소가 heap 메모리 영역 이어야 한다.

string a("asd");
shared_ptr<string> p(&a); // 사용 안됨.

 

 

'Cpp' 카테고리의 다른 글

허상 포인터(댕글링 포인터)  (0) 2023.06.19
L-value, R-value  (0) 2023.06.19
얕은 복사 깊은 복사  (0) 2023.06.13
함수 포인터  (0) 2023.06.13
포인터  (0) 2023.06.12