Menu
Coddy logo textTech

C++의 스마트 포인터

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 15번째.

스마트 포인터(Smart pointers)는 힙 메모리를 자동으로 관리해 주는 래퍼 클래스입니다. 포인터가 범위를 벗어날 때 메모리를 정리함으로써 수동으로 delete를 호출할 필요를 없애줍니다.

스마트 포인터를 사용하려면 <memory> 헤더를 포함하세요.

unique_ptr - 독점적 소유권. 한 번에 하나의 포인터만 리소스를 소유할 수 있습니다.

#include <memory>

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // 일반 포인터처럼 사용

// 복사할 수 없지만, 소유권을 이전할 수 있음
std::unique_ptr<Player> player2 = std::move(player);
// player는 이제 nullptr임

shared_ptr - 공유 소유권. 여러 포인터가 동일한 리소스를 소유할 수 있습니다. 마지막 소유자가 소멸될 때 메모리가 해제됩니다.

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // 둘 다 리소스를 소유합니다

std::cout << p1.use_count();  // 2를 출력합니다

weak_ptr - shared_ptr의 소유권이 없는 관찰자입니다. 순환 참조를 끊는 데 유용합니다.

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // shared_ptr로 변환
    locked->attack();
}

단일 소유권을 위해 기본적으로 unique_ptr을 사용하세요. 여러 객체가 리소스를 공유해야 할 때는 shared_ptr을 사용하세요. 수명을 연장하지 않고 관찰하려면 weak_ptr을 사용하세요.

raw new보다는 make_uniquemake_shared를 사용하는 것이 좋습니다.

challenge icon

챌린지

쉬움

스마트 포인터의 다양한 소유권 모델을 보여주는 문서 공유 시스템을 구축해 보겠습니다. unique_ptr이 독점적 소유권을 강제하는 방법, shared_ptr이 여러 소유자를 허용하는 방법, 그리고 weak_ptr이 수명에 영향을 주지 않고 관찰하는 방법을 배우게 됩니다.

코드를 구성하기 위해 두 개의 파일을 생성합니다:

  • Document.h: 공유 가능한 문서를 나타내는 Document 클래스를 정의합니다. 다음을 포함해야 합니다:
    • 프라이빗 title 속성 (string)
    • 제목을 매개변수로 받아 "Document created: <title>"를 출력하는 생성자
    • "Document deleted: <title>"를 출력하는 소멸자
    • 제목을 반환하는 getTitle() 메서드
  • main.cpp: 입력으로부터 문서 제목을 읽어 세 가지 스마트 포인터 유형을 모두 시연합니다:
    • 입력받은 제목으로 Document에 대한 unique_ptr을 생성합니다.
    • "Unique owner: <title>"를 출력합니다.
    • std::move를 사용하여 소유권을 다른 unique_ptr로 이전합니다.
    • "Ownership transferred"를 출력합니다.
    • 제목이 "SharedDoc"인 새 Document에 대한 shared_ptr을 생성합니다.
    • 동일한 문서를 가리키는 두 번째 shared_ptr을 생성합니다.
    • use_count()를 사용하여 "Shared owners: <count>"를 출력합니다.
    • 공유 포인터 중 하나로부터 weak_ptr을 생성합니다.
    • lock()을 사용하여 약한 포인터를 통해 문서에 접근하고 "Weak access: <title>"를 출력합니다.

스마트 포인터를 사용하려면 <memory>를 포함해야 함을 기억하세요. 스마트 포인터를 생성할 때는 std::make_uniquestd::make_shared를 사용하세요. 소멸자 메시지는 프로그램이 끝날 때 각 문서가 언제 자동으로 정리되는지 확인하는 데 도움이 됩니다.

main.cpp에 #include "Document.h"를 사용하여 헤더 파일을 포함하세요.

치트 시트

스마트 포인터는 힙 메모리를 자동으로 관리하는 래퍼 클래스입니다. 이를 사용하려면 <memory> 헤더를 포함하세요.

unique_ptr

독점적 소유권 - 한 번에 하나의 포인터만 리소스를 소유할 수 있습니다:

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // 일반 포인터처럼 사용

// std::move를 사용하여 소유권 이전
std::unique_ptr<Player> player2 = std::move(player);
// player는 이제 nullptr입니다

shared_ptr

공유 소유권 - 여러 포인터가 동일한 리소스를 소유할 수 있습니다. 마지막 소유자가 소멸될 때 메모리가 해제됩니다:

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // 둘 다 리소스를 소유함

std::cout << p1.use_count();  // 2를 출력함

weak_ptr

shared_ptr를 소유하지 않고 관찰하는 관찰자입니다. 순환 참조를 끊는 데 유용합니다:

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // shared_ptr로 변환
    locked->attack();
}

권장 사항: 단일 소유권의 경우 기본적으로 unique_ptr를 사용하세요. 여러 객체가 리소스를 공유해야 할 때는 shared_ptr를 사용하세요. 수명을 연장하지 않고 관찰하려면 weak_ptr를 사용하세요. 가급적 원시 new 대신 make_uniquemake_shared를 사용하세요.

직접 해보기

#include <iostream>
#include <memory>
#include <string>
#include "Document.h"

using namespace std;

int main() {
    string inputTitle;
    cin >> inputTitle;

    // TODO: inputTitle을 사용하여 Document에 대한 unique_ptr 생성
    // std::make_unique 사용

    // TODO: "Unique owner: <title>" 출력

    // TODO: std::move를 사용하여 다른 unique_ptr로 소유권 이전

    // TODO: "Ownership transferred" 출력

    // TODO: 제목이 "SharedDoc"인 새로운 Document에 대한 shared_ptr 생성
    // std::make_shared 사용

    // TODO: 동일한 문서를 가리키는 두 번째 shared_ptr 생성

    // TODO: use_count()를 사용하여 "Shared owners: <count>" 출력

    // TODO: shared pointers 중 하나로부터 weak_ptr 생성

    // TODO: lock()을 사용하여 weak_ptr를 통해 문서에 접근
    // 그리고 "Weak access: <title>" 출력

    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨