44. std::vector<bool> 특수화와 프록시 참조

난이도 중 해설 보기 →

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

결함 코드 · C++
// [주제] std::vector<bool> 특수화
//
// [과제]
// 1. 아래 프로그램의 출력을 예측하시오. 컴파일 오류가 나는 줄이 있다면 어느 줄이고 왜인지
//    설명하시오. (지금은 해당 줄이 주석 처리되어 있다.)
// 2. sizeof(bool) 이 1인 플랫폼에서 vb 와 vc 의 메모리 사용량이 왜 다른지 설명하시오.
// 3. printFirst 와 flipFirst 안의 auto 가 각각 어떤 타입으로 추론되는지 두 컨테이너에 대해
//    답하시오. 두 함수에서 결과가 갈리는가? 갈린다면(또는 갈리지 않는다면) 그 이유는?
// 4. 표준 컨테이너의 어떤 일반 규약이 vector<bool> 에서 성립하지 않는지 열거하고,
//    그것이 제네릭 코드에 어떤 영향을 주는지 설명하시오.
//
// 게임서버 맥락: 플레이어별 퀘스트 완료 플래그, AoI 가시성 마스크, 스킬 슬롯 사용 여부처럼
// 대량의 불리언을 다루는 자료구조에서 이 특수화가 실제로 문제를 일으킨다.

#include <cstdio>
#include <typeinfo>
#include <vector>

template <class Container>
void printFirst(const Container& c) {
    auto first = c[0];
    std::printf("first=%d, sizeof(elem-proxy)=%zu\n",
                static_cast<int>(first), sizeof(first));
}

template <class Container>
void flipFirst(Container& c) {
    auto x = c[0];
    x = true;                 // x 를 통해 컨테이너를 바꾸려는 시도
}

int main() {
    std::vector<bool> vb(8, false);
    std::vector<char> vc(8, 0);

    std::printf("A: %zu %zu\n", sizeof(vb), sizeof(vc));

    printFirst(vb);
    printFirst(vc);

    flipFirst(vb);
    flipFirst(vc);
    std::printf("B: %d %d\n", static_cast<int>(vb[0]), static_cast<int>(vc[0]));

    // 아래 줄들은 왜 문제가 되는가?
    // bool& r = vb[0];
    // bool* p = &vb[0];

    vb[3] = true;
    std::printf("C: %d\n", static_cast<int>(vb[3]));

    std::vector<bool> big(5000, false);
    auto ref = vb[3];
    vb = big;                         // 대입으로 내부 버퍼가 교체될 수 있다
    std::printf("D: %d\n", static_cast<int>(ref));

    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

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