Skip to main content
Summary

1. 메모리 구조 (Memory Layout)

프로그램이 실행될 때 메모리는 크게 네 영역으로 나뉩니다.

  • Code (Text) 영역: 실행할 프로그램의 명령어(기계어)가 저장되는 읽기 전용 영역.

  • Data 영역: 전역 변수(Global)와 정적 변수(Static)가 저장됨. 프로그램 시작 시 할당, 종료 시 해제.

  • Stack 영역: 함수 호출 시 생성되는 지역 변수와 매개 변수. 자동으로 관리되며 LIFO(Last-In-First-Out) 구조.

  • Heap 영역: new나 malloc으로 할당하는 동적 메모리. 사용자가 직접 해제해야 함 (delete/free). 해제하지 않으면 메모리 누수 발생.

2. 포인터(Pointer) vs 참조자(Reference)

  • 포인터 (int* ptr)* 주소값을 저장하는 변수. nullptr 가능, 가리키는 대상 변경 가능.

  • 참조자 (int& ref): 변수의 별명. 선언 시 반드시 초기화 필수, nullptr 불가능, 대상 변경 불가능.

3. 객체 지향 프로그래밍 (OOP) 핵심

  1. 캡슐화: 데이터와 기능을 하나로 묶고 접근 제어(public, private)로 보호.

  2. 상속: 부모 클래스의 특성을 물려받아 재사용.

  3. 다형성: 같은 인터페이스로 서로 다른 동작을 수행 (오버로딩, 오버라이딩).

  4. 추상화: 복잡한 내부 로직을 숨기고 필요한 인터페이스만 노출.

4. 오버로딩 vs 오버라이딩

  • 오버로딩 (Overloading): 같은 함수 이름, 다른 매개변수 (컴파일 타임).

  • 오버라이딩 (Overriding): 상속 관계에서 부모 함수를 자식이 재정의 (런타임, virtual 필요).

5. 가상 함수 테이블 (Virtual Function Table, V-Table)

  • 정의: 가상 함수를 가진 클래스마다 하나씩 생성되는 함수 주소 배열.

  • vptr: 각 객체가 가지고 있는 숨겨진 포인터로, 소속 클래스의 V-Table을 가리킴.

  • 동작: 부모 포인터로 함수 호출 시, 객체의 vptr을 통해 V-Table에 접속하여 실제 오버라이딩된 함수의 주소를 찾아 실행함 (동적 바인딩).

6. 가상 소멸자 (Virtual Destructor)

  • 상속 관계에서 부모 클래스 포인터로 자식 객체를 delete 할 때, 자식 클래스의 소멸자가 호출되지 않는 문제를 방지하기 위해 부모 소멸자에 virtual을 반드시 붙여야 함.

7. 캐스팅 (Casting)

  • static_cast: 일반적인 타입 변환 (논리적으로 연관 있는 타입).

  • dynamic_cast: 상속 관계의 안전한 다운 캐스팅 (런타임에 타입 체크, RTTI 필요).

  • const_cast: const 성질을 제거할 때 사용.

8. STL 컨테이너 시간 복잡도

  • vector: 임의 접근 $O(1)$, 끝부분 삽입/삭제 $O(1)$, 중간 삽입/삭제 $O(N)$.

  • list: 임의 접근 $O(N)$, 삽입/삭제 $O(1)$.

  • map / set: 이진 탐색 트리 기반, 정렬됨. 탐색/삽입 $O(\log N)$.

  • unordered_map: 해시 테이블 기반. 탐색/삽입 평균 $O(1)$.

9. 주요 키워드

  • const: 값의 변경을 막음.

    • const int* p: 데이터가 상수.

    • int* const p: 포인터가 상수.

  • static:

    • 지역 변수: 함수가 끝나도 값 유지.

    • 멤버 변수: 객체 간 공유되는 클래스 변수.

  • inline: 함수 호출 오버헤드를 줄이기 위해 코드 본문을 직접 삽입하도록 컴파일러에 권장.

10. 스마트 포인터 (Smart Pointers - <memory>)

자원 누수를 방지하기 위해 메모리를 자동으로 관리하는 객체.

  • unique_ptr: 특정 객체의 소유권을 독점함. 복사 불가능, std::move를 통한 이동만 가능.

  • shared_ptr: 참조 횟수(Reference Count)를 기반으로 소유권을 공유. 참조 횟수가 0이 되면 메모리 해제.

  • weak_ptr: shared_ptr의 순환 참조(Circular Reference) 문제를 해결하기 위해 사용. 소유권을 갖지 않고 객체 존재 여부만 확인.

11. R-value 참조와 이동 생성자 (Move Semantics)

불필요한 깊은 복사(Deep Copy)를 방지하여 성능을 최적화함.

  • L-value: 이름이 있고 주소를 취할 수 있는 변수.

  • R-value: 임시 객체와 같이 곧 사라지는 값.

  • std::move: L-value를 R-value로 캐스팅하여 이동 생성자가 호출되도록 유도. 자원을 복사하는 대신 '탈취'함.

12. RAII (Resource Acquisition Is Initialization)

  • 개념: 자원 획득은 초기화와 동시에 이루어져야 하며, 자원의 수명은 객체의 수명과 일치해야 함.

  • 응용: 스마트 포인터, std::lock_guard 등이 대표적임. 생성자에서 자원을 할당받고 소멸자에서 해제하여 예외 상황에서도 자원 누수를 방지.

13. 람다 캡처 (Lambda Capture)

함수 객체를 익명으로 생성할 때 외부 변수를 사용하는 방식.

  • [ ]: 캡처 없음.

  • [=]: 외부의 모든 변수를 값으로 복사하여 사용 (읽기 전용).

  • [&]: 외부의 모든 변수를 참조로 사용 (원본 수정 가능).

  • [x, &y]: x는 값으로, y는 참조로 선택적 캡처.

14. 복사 생성자 vs 대입 연산자 (Rule of Three/Five)

클래스가 동적 할당 자원을 관리할 때 정의해야 하는 멤버들.

  1. 소멸자 (Destructor)

  2. 복사 생성자 (Copy Constructor)

  3. 복사 대입 연산자 (Copy Assignment Operator)

  4. (C++11 추가) 이동 생성자 (Move Constructor)

  5. (C++11 추가) 이동 대입 연산자 (Move Assignment Operator)

15. 가상 상속 (Virtual Inheritance) - 다이아몬드 문제

  • 문제 상황: 클래스 B와 C가 A를 상속받고, D가 B와 C를 동시에 상속받을 때 A의 멤버가 중복 생성되는 문제.

  • 해결: class B : virtual public A 형태로 상속받으면, 최하위 자식 객체 내에 부모 클래스(A)의 인스턴스가 단 하나만 존재하도록 보장함.

16. 완벽한 전달 (Perfect Forwarding)

  • 개념: 전달받은 인수의 L-value/R-value 속성을 그대로 유지하며 다른 함수로 전달하는 기술.

  • 핵심: 템플릿의 보편적 참조(Universal Reference) T&&와 std::forward<T>()를 조합하여 사용.

17. SFINAE 및 enable_if (Template Metaprogramming)

  • SFINAE: "Substitution Failure Is Not An Error" (치환 실패는 에러가 아니다). 템플릿 인자 치환에 실패해도 다른 오버로딩 후보를 계속 찾는 성질.

  • std::enable_if: 특정 조건(예: 정수 타입일 때만)에 따라 템플릿 함수를 활성화하거나 비활성화할 때 사용.

  • CPP 20 에서는 enable_if 가 아닌 'require' 로 사용함

18. CRTP (Curiously Recurring Template Pattern)

  • 개념: 자식 클래스가 자신의 이름을 부모 클래스의 템플릿 인자로 넘겨 상속받는 패턴.

  • 목적: 가상 함수 테이블(V-Table)을 거치지 않는 정적 다형성을 구현하여 실행 시간 성능을 최적화함.

    template <typename T> class Base { ... };
    class Derived : public Base<Derived> { ... };
    ex) static_cast<T*>(this)->자식함수이름();

19. 예외 안정성 (Exception Safety)

  1. 기본 보장 (Basic): 예외 발생 시 자원 누수는 없으나 객체의 상태를 예측할 수 없음.

  2. 강력한 보장 (Strong): 예외 발생 시 호출 전 상태로 완벽히 복구 (Rollback). 보통 copy-and-swap 기법 사용.

  3. 예외 불가 보장 (No-throw): 절대 예외를 던지지 않음 (noexcept 키워드).

20. 메모리 정렬 및 패딩 (Memory Alignment & Padding)

  • 성능 최적화를 위해 CPU가 데이터를 읽기 좋은 단위(4/8바이트 등)로 정렬함.

  • 이로 인해 구조체 내부 멤버 사이에 빈 공간(Padding)이 생길 수 있으며, 멤버 선언 순서에 따라 sizeof(struct) 결과가 달라질 수 있음.

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기