포인터 변수를 통해 동적할당 했을 때에는 항상 해제를 해주어야한다.
그래서 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 |