39. std::optional 의 내부 동작과 값 의미론

난이도 중 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C++
// 주제: std::optional 의 내부 동작과 값 의미론.
//
// 과제:
//  1) 아래 프로그램의 출력을 정확히 예측하라(생성/이동/소멸 로그 포함).
//  2) optional<T> 가 T 를 어디에(힙 vs 자기 저장소) 담는지, has_value/engaged 상태,
//     emplace/reset 이 담긴 객체의 생성자·소멸자를 언제 호출하는지 예측·설명하라.
//  3) operator*/operator-> 와 value()의 차이(전제조건 vs 예외), 그리고 빈 optional 에
//     대한 fallback 이 어느 시점에 평가되는지 설명하라.

#include <iostream>
#include <optional>
#include <string>

struct Tracked {
    std::string name;
    Tracked(std::string n) : name(std::move(n)) { std::cout << "ctor " << name << "\n"; }
    Tracked(const Tracked& o) : name(o.name) { std::cout << "copy " << name << "\n"; }
    Tracked(Tracked&& o) noexcept : name(std::move(o.name)) { std::cout << "move " << name << "\n"; }
    ~Tracked() { std::cout << "dtor " << name << "\n"; }
};

std::string fallback() { std::cout << "fallback()\n"; return "FB"; }

int main() {
    std::cout << "-- 1 --\n";
    std::optional<Tracked> o;                  // (관찰) 담긴 값 유무
    std::cout << "engaged=" << o.has_value() << "\n";

    std::cout << "-- 2 --\n";
    o.emplace("A");                            // (A)
    std::cout << "engaged=" << o.has_value() << "\n";

    std::cout << "-- 3 --\n";
    o.reset();                                 // (B)
    std::cout << "engaged=" << o.has_value() << "\n";

    std::cout << "-- 4 --\n";
    std::optional<Tracked> p{Tracked("B")};    // (C) 임시로부터 초기화
    std::cout << "operator-> 접근\n";
    std::string s = p->name;
    std::cout << "name=" << s << "\n";

    std::cout << "-- 5 --\n";
    std::optional<Tracked> q;                  // 비어 있음
    std::string r = q ? q->name : fallback();  // (D) 분기 평가
    std::cout << "r=" << r << "\n";

    std::cout << "-- end --\n";
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.