본문 바로가기
다양한 TIP

참조하는 객체가 지워졌는지 확인하려면? std::weak_ptr

by 유기농프로그래밍 2025. 4. 2.
반응형

바라보는 포인터가 갑자기 삭제됐을 때 바라보던 포인터들이 알아채고 null처리를 할 수 있다면? 하는 생각 해보셨나요?

이 때 필요한게 바로 weak_ptr 입니다. 객체는 참조하여 카운트를 유지하는 shared_ptr과는 다르게 "관찰"하는 포인터인데요. 한번 알아볼까요?


1. 기본 개념

  • std::shared_ptr
    : 객체의 소유권을 공유합니다. 참조 카운트를 유지하여, 모든 shared_ptr가 소멸되면 객체가 파괴됩니다.
  • std::weak_ptr
    : 객체의 소유권은 가지지 않고, 단순히 shared_ptr로 관리되는 객체를 "관찰"합니다.
    : 객체가 여전히 살아 있으면 lock() 함수를 통해 std::shared_ptr를 얻을 수 있고, 객체가 소멸되면 lock()은 빈 shared_ptr(nullptr)를 반환합니다.

2. 사용 방법

(1) std::weak_ptr 생성

std::weak_ptr는 std::shared_ptr로부터 생성됩니다.

#include <memory>
#include <iostream>

struct MyData {
    int value;
};

int main() {
    // shared_ptr를 사용해 객체를 생성 및 관리합니다.
    std::shared_ptr<MyData> sp = std::make_shared<MyData>();
    sp->value = 42;
    
    // shared_ptr로부터 weak_ptr를 생성합니다.
    std::weak_ptr<MyData> wp = sp;

    // weak_ptr는 소유권은 없지만, 객체를 관찰할 수 있습니다.
    return 0;
}

(2) std::weak_ptr의 객체 접근

weak_ptr는 직접 객체에 접근할 수 없고, lock() 메소드를 사용해 임시로 shared_ptr를 생성해야 합니다. 이때 객체가 이미 소멸되었다면, lock()은 빈(shared_ptr(nullptr))을 반환합니다.

if (auto observed = wp.lock()) {
    // 객체가 유효할 때, observed는 유효한 shared_ptr입니다.
    std::cout << "Value: " << observed->value << std::endl;
} else {
    // 객체가 이미 소멸된 경우
    std::cout << "Object has been deleted." << std::endl;
}

 

(3) 객체 소멸 후 weak_ptr 상태 확인

객체가 소멸되면 weak_ptr는 만료(expired) 상태가 됩니다.

// 객체가 소멸되기 전
if (!wp.expired()) {
    std::cout << "Object is still alive." << std::endl;
}

// 객체 소멸: 모든 shared_ptr가 소멸하면
sp.reset();

if (wp.expired()) {
    std::cout << "Object has been deleted, weak_ptr expired." << std::endl;
}

 

3. 전체 예제 코드

아래는 std::shared_ptr와 std::weak_ptr의 기본 사용 예제를 보여줍니다.

#include <iostream>
#include <memory>

struct MyData {
    int value;
};

int main() {
    // shared_ptr를 생성하고 객체를 초기화
    std::shared_ptr<MyData> sp = std::make_shared<MyData>();
    sp->value = 42;
    
    // weak_ptr를 생성하여 sp를 관찰합니다.
    std::weak_ptr<MyData> wp = sp;
    
    // weak_ptr를 통해 객체 접근
    if (auto observed = wp.lock()) {
        std::cout << "Observed value: " << observed->value << std::endl;
    } else {
        std::cout << "Object has been deleted." << std::endl;
    }
    
    // 객체 소멸: sp를 리셋하여 참조 카운트를 0으로 만듭니다.
    sp.reset();
    
    // 소멸 후 weak_ptr 상태 확인
    if (wp.expired()) {
        std::cout << "weak_ptr is expired. Object no longer exists." << std::endl;
    } else {
        std::cout << "Object is still alive." << std::endl;
    }
    
    // lock() 결과는 nullptr가 됩니다.
    auto observedAfter = wp.lock();
    if (!observedAfter) {
        std::cout << "Locking weak_ptr returned nullptr." << std::endl;
    }
    
    return 0;
}

 


4. 요약

  • 생성: std::weak_ptr<T> wp = sp; (여기서 sp는 std::shared_ptr<T>입니다.)
  • 접근: auto observed = wp.lock();를 사용하여 객체가 유효한지 확인합니다.
  • 만료 확인: wp.expired()로 객체가 소멸되었는지 판단할 수 있습니다.

이러한 방식으로 여러 위치에서 동일한 객체를 관찰할 때, 원본 객체가 소멸되면 자동으로 weak_ptr를 통해 "null" 상태를 확인할 수 있습니다.

반응형

댓글