왜 쓰나?
스마트 포인터는 new/delete를 직접 관리하는 대신, 수명(lifetime)을 자동으로 관리해서 메모리 누수와 해제 실수를 줄입니다.
std::unique_ptr (단독 소유)
소유권이 하나의 포인터에만 존재합니다. 복사는 불가하고 이동(move) 만 가능합니다.
#include <memory>
int main() {
auto p = std::make_unique<int>(10); // p가 유일하게 소유
auto q = std::move(p); // 소유권 이동 (p는 null처럼 비어 있음)
}
std::shared_ptr (공유 소유)
여러 곳에서 같은 객체를 참조하며, 참조 카운트가 0이 되면 자동 해제됩니다.
#include <iostream>
#include <memory>
int main() {
auto a = std::make_shared<int>(5);
auto b = a; // 참조 카운트 증가
std::cout << *a << ", " << *b << "\n";
}
std::weak_ptr (약한 참조, 순환 참조 방지)
shared_ptr와 함께 쓰이며, 참조 카운트를 늘리지 않습니다. 그래서 서로가 서로를 들고 있는 **순환 참조(cycle)**를 막을 때 유용합니다.
#include <iostream>
#include <memory>
struct Node {
std::weak_ptr<Node> parent; // weak: 참조 카운트 증가 안 함
std::shared_ptr<Node> child; // shared: 소유
};
int main() {
auto root = std::make_shared<Node>();
auto leaf = std::make_shared<Node>();
root->child = leaf;
leaf->parent = root;
// scope 벗어나면 shared는 해제되고, weak은 검사(lock으로 접근)
if (auto locked = leaf->parent.lock()) {
std::cout << "parent exists\n";
}
}
한 줄 요약
unique_ptr: 단독 소유shared_ptr: 공유 소유weak_ptr: 공유 소유를 “안전하게 바라보기”(순환 방지)