본문 바로가기
프로그래밍/C++

C++11 주요 업데이트 : override, final, std::thread, std::array

by 머니테크리더 2023. 9. 30.
반응형

C++11 주요 업데이트 : override, final, std::thread, std::array
C++11 주요 업데이트 : override, final, std::thread, std::array

 

🔖 INDEX

     

     

    override와 final

    C++11에서는 클래스 상속과 관련하여 두 가지 새로운 키워드, override와 final을 도입했습니다. 이 두 키워드는 코드의 명시성과 안정성을 높이기 위해 클래스 상속과 오버라이드 시 사용됩니다. 이러한 키워드를 통해 프로그래머의 의도를 더욱 명확하게 표현할 수 있게 되었습니다.

     

    override

    • 개념: override 키워드는 파생 클래스에서 기본 클래스의 가상 함수를 오버라이드하고 있다는 것을 명시적으로 나타내기 위해 사용됩니다.
    • 장점: 이 키워드를 사용하면, 실수로 함수를 오버라이드하지 않은 경우(예: 함수의 서명이 일치하지 않을 때) 컴파일러가 경고 혹은 오류를 발생시켜 줍니다.
    class Base {
    public:
        virtual void func() {}
    };
    
    class Derived : public Base {
    public:
        void func() override {}  // 명시적으로 오버라이드하고 있음을 표시
    };

     

    final

    • 개념: final 키워드는 두 가지 방식으로 사용될 수 있습니다.
      1. 클래스에 final이 붙으면, 해당 클래스를 상속하는 것을 금지합니다.
      2. 가상 함수에 final이 붙으면, 해당 함수를 추가로 오버라이드하는 것을 금지합니다.
    • 장점:
      1. 클래스에 final을 사용하면, 의도치 않은 파생 클래스의 생성을 방지할 수 있습니다.
      2. 가상 함수에 final을 사용하면, 파생 클래스에서 해당 함수의 오버라이드를 방지함으로써, 특정 함수의 동작을 고정시킬 수 있습니다.
    class Base {
    public:
        virtual void func() final {}  // 추가로 오버라이드 금지
    };
    
    class FinalClass final {  // 상속 금지
    public:
        void someFunction() {}
    };
    
    // class Derived : public FinalClass {}  // 오류: FinalClass는 상속될 수 없습니다.

     

    주의사항

    • override와 final 키워드는 가상 함수와 함께 사용될 때만 의미가 있습니다.
    • override는 함수의 구현부에서는 사용되지 않고, 선언부에서만 사용됩니다.

     

     

    C++11 Standard Thread Library

    C++11에서는 멀티스레딩 프로그래밍을 위한 표준 라이브러리가 도입되었습니다. 이 라이브러리를 사용하면 운영 체제에 의존하지 않고 플랫폼 간 이식성이 높은 멀티스레딩 코드를 작성할 수 있습니다.

     

    <thread>

    기본적인 스레드 관리: std::thread 클래스를 통해 스레드를 생성하고 관리할 수 있습니다.

    #include <iostream>
    #include <thread>
    
    void myFunction() {
        std::cout << "Hello from thread!" << std::endl;
    }
    
    int main() {
        std::thread t(myFunction);
        t.join();  // 주 스레드에서 t 스레드가 종료될 때까지 기다립니다.
    }

     

    <mutex>

    뮤텍스: 데이터의 동시 접근을 제어하기 위한 동기화 메커니즘이 필요한데, std::mutex는 이런 동기화를 위해 사용됩니다.

    #include <iostream>
    #include <thread>
    #include <mutex>
    
    std::mutex mtx;
    
    void printWithLock(int id) {
        mtx.lock();
        std::cout << "Thread " << id << " is running." << std::endl;
        mtx.unlock();
    }
    
    int main() {
        std::thread t1(printWithLock, 1);
        std::thread t2(printWithLock, 2);
        t1.join();
        t2.join();
    }

     

    <condition_variable>

    조건 변수: std::condition_variable은 특정 조건이 충족될 때까지 스레드를 대기시키는데 사용됩니다.

     

    <future>, <promise>

    비동기 작업과 결과: std::async, std::future, std::promise 등은 비동기 작업의 결과를 추출하거나, 비동기 작업 간의 데이터 전송을 위해 사용됩니다.

    #include <iostream>
    #include <future>
    
    int compute() { return 10; }
    
    int main() {
        std::future<int> result = std::async(compute);
        std::cout << "Result: " << result.get() << std::endl;  // 여기서 결과를 기다리고, 10을 출력합니다.
    }

     

    기타 도구들

    • <atomic>: 원자적 연산을 지원하는 타입들과 함수들을 제공합니다.
    • <chrono>: 시간과 관련된 기능들을 제공합니다. 예를 들어 스레드를 일정 시간 동안 대기시킬 때 사용됩니다.

     

    주의사항

    • 데드락: 여러 스레드가 서로의 자원을 기다리며 무한 대기하는 상태. 이러한 상황을 피하기 위해 꼭 필요한 경우에만 락을 사용하고, 가능한 한 짧은 시간 동안만 락을 유지해야 합니다.
    • 레이스 컨디션: 두 스레드 이상이 동일한 자원에 동시에 접근하여 발생하는 문제. 이를 방지하기 위해 적절한 동기화 메커니즘이 필요합니다.

     

     

    C++11 Standard Array (std::array)

    C++11에서는 고정 크기의 배열을 나타내는 std::array가 도입되었습니다. 전통적인 C-style 배열의 단점들을 보완하면서, STL과의 호환성을 갖춘 컨테이너로써 디자인되었습니다.

     

    기본 사용법

    std::array는 헤더 파일 <array>에 정의되어 있습니다.

    #include <array>
    #include <iostream>
    
    int main() {
        std::array<int, 5> arr = {1, 2, 3, 4, 5};
    
        for (int num : arr) {
            std::cout << num << " ";
        }
    }

     

    주요 특징

    • 고정 크기: std::array는 생성 시에 크기가 정해집니다. 이 크기는 런타임 동안 변경될 수 없습니다.
    • Stack 메모리: std::array는 스택 메모리에 할당됩니다. 따라서 동적 메모리 할당과 관련된 오버헤드나 메모리 누수에 대한 걱정이 덜합니다.
    • STL 호환성: std::array는 STL 알고리즘과 함께 사용하기 좋습니다. begin(), end()와 같은 멤버 함수를 제공하여, STL 알고리즘과의 호환성을 갖추고 있습니다.

     

    주요 멤버 함수

    • at(): 주어진 위치의 요소에 접근하며, 범위를 초과한 경우 예외를 발생시킵니다.
    • front() & back(): 첫 번째 요소와 마지막 요소에 접근합니다.
    • fill(): 배열의 모든 요소를 주어진 값으로 채웁니다.
    • size(): 배열의 크기를 반환합니다.
    • max_size(): 배열의 최대 크기(고정 크기)를 반환합니다.
    • empty(): 배열이 비어있는지 확인합니다. (std::array는 고정 크기이므로 항상 false를 반환합니다.)

     

    안전한 접근

    전통적인 C-style 배열에서는 배열의 범위를 초과하는 인덱스 접근에 대한 안전장치가 없습니다. 그러나 std::array의 at() 함수를 사용하면, 범위를 초과할 경우 std::out_of_range 예외가 발생하여 프로그래머에게 알려줍니다.

    try {
        int value = arr.at(10);  // 범위를 초과
    } catch (const std::out_of_range& e) {
        std::cout << "범위 초과 오류: " << e.what() << std::endl;
    }

     

     

     

    댓글