Smart Pointer는 프로그래머의 실수로 메모리 누수를 방어하기 위한 수단으로 포인터처럼 동작하는 클래스 템플릿이다. 일반적으로 new 키워드를 이용해 기본 포인터가 특정한 메모리 주소를 가리키도록 초기화 한 후 스마트 포인터에 해당 포인터를 넣어서 사용할 수 있다.
하나의 스마트 포인터만이 특정한 객체를 처리하도록 할 때 unique_ptr을 사용할 수 있다. 이 스마트 포인터는 특정한 객체의 소유권을 가지고 있을 때만 소멸자가 객체를 삭제할 수 있다.
#include<iostream>
using namespace std;
int main(void) {
unique_ptr<int> p1(new int(10));
unique_ptr<int> p2;
cout << "스마트포인터1: " << p1 << '\n';
cout << "스마트포인터2: " << p2 << '\n';
cout << "---소유권이전---\n";
p2 = move(p1); // 소유권이전
cout << "스마트포인터1: " << p1 << '\n';
cout << "스마트포인터2: " << p2 << '\n';
cout << "---메모리할당해제---\n";
p2.reset(); // 메모리할당해제
cout << "스마트포인터1: " << p1 << '\n';
cout << "스마트포인터2: " << p2 << '\n';
system("pause");
}
특정한 객체를 새로운 스마트 포인터가 참조할 때마다 참조 횟수가 1씩 증가하며 각 스마트 포인터의 수명이 다할 때마다 1씩 감소한다. 결과적으로 참조 횟수가 0이 되면 delete 키워드를 이용해 메모리에서 데이터를 자동으로 할당 해제한다.
#include<iostream>
using namespace std;
int main(void) {
int* arr = new int[10];
shared_ptr<int> p1(arr);
cout << p1.use_count() << '\n';
shared_ptr<int> p2(p1);
cout << p1.use_count() << '\n';
shared_ptr<int> p3 = p2;
cout << p1.use_count() << '\n';
p1.reset();
p2.reset();
p3.reset();
cout << p1.use_count() << '\n';
system("pause");
}
일반적으로 서로가 상대방을 가리키는 두 개의 shared_ptr가 있다면 참조 횟수는 0이 될 수 없기 때문에 메모리에서 해제될 수 없다. weak_ptr는 이러한 순환 참조 현상을 제거하기 위한 목적으로 사용할 수 있다.
#include<iostream>
using namespace std;
int main(void) {
int* arr = new int(1);
shared_ptr<int> sp1(arr);
weak_ptr<int> wp = sp1; // wp는 참조횟수계산에서 제외합니다.
cout << sp1.use_count() << '\n'; // 1로 동일합니다.
cout << wp.use_count() << '\n';
if (true) {
shared_ptr<int> sp2 = wp.lock(); // shared_ptr포인터반환
cout << sp1.use_count() << '\n';
cout << wp.use_count() << '\n';
}
// 스코프(Scope)를 벗어나므로 sp2가해제됩니다.
cout << sp1.use_count() << '\n';
cout << wp.use_count() << '\n';
system("pause");
}