카테고리 없음
[C++] Singleton weak_ptr 사용
2026. 4. 29. 12:46반응형
#include <iostream>
#include <memory>
#include <mutex>
// ============================================================
// Singleton: shared_ptr + weak_ptr 기반 수명 관리
// - 외부 shared_ptr이 모두 소멸 → ref count=0 → 자동 소멸
// - weak_ptr은 count에 영향 없음 (소유권 없는 관찰자)
// ============================================================
class Singleton {
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
// private 소멸자에 접근 가능한 custom deleter
struct Deleter {
void operator()(Singleton* p) const { delete p; }
};
static std::shared_ptr<Singleton> getInstance() {
std::lock_guard<std::mutex> lock(mutex_);
auto sp = instance_.lock(); // weak_ptr → shared_ptr 승격 시도
if (!sp) {
sp = std::shared_ptr<Singleton>(new Singleton(), Deleter{});
instance_ = sp; // weak_ptr 갱신 (count 영향 없음)
}
return sp;
}
void doSomething() const {
std::cout << " doSomething() called. value=" << value_ << "\n";
}
void setValue(int v) { value_ = v; }
int getValue() const { return value_; }
private:
Singleton() : value_(0) {
std::cout << "[+] Singleton constructed\n";
}
~Singleton() {
std::cout << "[-] Singleton destroyed\n";
}
static std::weak_ptr<Singleton> instance_;
static std::mutex mutex_;
int value_;
};
std::weak_ptr<Singleton> Singleton::instance_;
std::mutex Singleton::mutex_;
// ============================================================
// 전달 방식별 ref count 변화 확인용 함수들
// ============================================================
// 1) 값 전달 → 복사 → count+1
void byValue(std::shared_ptr<Singleton> sp) {
std::cout << " [byValue] use_count=" << sp.use_count() << "\n";
}
// 2) const 참조 전달 → count 변화 없음
void byConstRef(const std::shared_ptr<Singleton>& sp) {
std::cout << " [byConstRef] use_count=" << sp.use_count() << "\n";
}
// 3) move 전달 → 소유권 이전, count 변화 없음, 원본 nullptr
void byMove(std::shared_ptr<Singleton> sp) {
std::cout << " [byMove] use_count=" << sp.use_count()
<< " (소유권 이전됨)\n";
}
int main() {
std::cout << "=== 1. 기본 생성 및 소멸 ===\n";
{
auto s1 = Singleton::getInstance(); // count=1
std::cout << " s1 use_count=" << s1.use_count() << "\n";
{
auto s2 = Singleton::getInstance(); // count=2
std::cout << " s2 use_count=" << s2.use_count() << "\n";
} // s2 소멸 → count=1
std::cout << " s2 소멸 후 s1 use_count=" << s1.use_count() << "\n";
} // s1 소멸 → count=0 → ~Singleton() 호출
std::cout << "\n=== 2. 소멸 후 재생성 ===\n";
{
auto s3 = Singleton::getInstance(); // 새로 생성
s3->setValue(99);
s3->doSomething();
} // 소멸
std::cout << "\n=== 3. 값 전달 (count+1) ===\n";
{
auto s1 = Singleton::getInstance(); // count=1
std::cout << " 호출 전 use_count=" << s1.use_count() << "\n";
byValue(s1); // 함수 내 count=2
std::cout << " 호출 후 use_count=" << s1.use_count() << "\n"; // count=1
}
std::cout << "\n=== 4. const 참조 전달 (count 유지) ===\n";
{
auto s1 = Singleton::getInstance();
std::cout << " 호출 전 use_count=" << s1.use_count() << "\n";
byConstRef(s1);
std::cout << " 호출 후 use_count=" << s1.use_count() << "\n";
}
std::cout << "\n=== 5. move 전달 (소유권 이전) ===\n";
{
auto s1 = Singleton::getInstance();
std::cout << " move 전 use_count=" << s1.use_count() << "\n";
byMove(std::move(s1)); // s1 → nullptr
std::cout << " move 후 s1 is nullptr? "
<< (s1 == nullptr ? "YES" : "NO") << "\n";
} // byMove 내부 sp 소멸 → count=0 → ~Singleton()
std::cout << "\n=== 6. 동일 인스턴스 확인 ===\n";
{
auto s1 = Singleton::getInstance();
auto s2 = Singleton::getInstance();
std::cout << " same instance? "
<< (s1.get() == s2.get() ? "YES" : "NO") << "\n";
std::cout << " use_count=" << s1.use_count() << "\n";
}
std::cout << "\n[main 종료]\n";
return 0;
}
# C++17 이상 필요
g++ -std=c++17 -Wall -Wextra -o singleton main.cpp
./singleton반응형