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

C++11 주요 업데이트 : auto, nullptr, 람다 식

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

C++11 주요 업데이트 : auto, nullptr, 람다 식
C++11 주요 업데이트 : auto, nullptr, 람다 식

🔖 INDEX

     

     

    자동 형식 추론 (auto)

    auto는 C++11에서 도입된 키워드로, 변수의 타입을 컴파일러가 자동으로 추론하게 하는 기능입니다. 즉, 개발자는 변수의 정확한 타입을 명시하지 않고 auto 키워드를 사용하여 컴파일러에게 타입 추론을 맡길 수 있습니다.

     

    auto 사용 예

    auto i = 42;       // int
    auto d = 3.14;     // double
    auto s = "hello";  // const char*
    auto v = std::vector<int>{1, 2, 3};  // std::vector<int>

    이처럼 auto는 변수의 초기화식을 기반으로 해당 변수의 타입을 추론합니다.

     

    auto의 장점

    • 가독성 향상: 복잡한 타입명을 반복적으로 작성할 필요가 없어 코드가 더 간결하고 가독성이 향상됩니다.
    • 타입 안정성: 컴파일러가 타입을 추론하기 때문에 실수로 잘못된 타입을 지정하는 오류를 방지할 수 있습니다.
    • 코드 유지보수: 코드의 일부분에 변경이 생겨도 auto를 사용한 부분은 자동으로 타입이 조정되므로 유지보수가 용이합니다.

     

    auto의 주의사항

    • 명확성: auto는 코드의 간결성을 제공하지만, 어떤 타입을 의미하는지 명확히 알 수 없을 때도 있습니다. 따라서 사용 시 주의가 필요합니다.
    • 초기화 필요: auto를 사용한 변수는 반드시 초기화 되어야 합니다. 그렇지 않으면 컴파일러는 타입을 추론할 수 없습니다.

     

    범위 기반 for 루프

    C++11부터는 컨테이너나 배열의 모든 요소를 쉽게 순회할 수 있는 '범위 기반 for 루프'라는 편리한 문법이 도입되었습니다. 전통적인 for 루프는 인덱스나 반복자를 이용하여 컨테이너의 요소를 순회하는 데 사용되었습니다. 반면, 범위 기반 for 루프는 컨테이너의 시작부터 끝까지 모든 요소를 자동으로 순회하면서 각 요소에 접근할 수 있게 해주는 문법입니다.

     

    범위 기반 for 루프 사용 예

    std::vector<int> vec = {1, 2, 3, 4, 5};
    for(auto num : vec) {
        std::cout << num << " ";
    }
    
    int arr[] = {10, 20, 30, 40};
    for(auto val : arr) {
        std::cout << val << " ";
    }

     

    범위 기반 for 루프의 장점

    • 간결성: 인덱스나 반복자를 사용하는 전통적인 for 루프에 비해 코드가 훨씬 간결해집니다.
    • 가독성 향상: 코드의 의도가 명확하게 드러나므로 가독성이 향상됩니다.
    • 오류 감소: 인덱스나 반복자를 잘못 사용하는 실수를 줄일 수 있습니다.

     

    범위 기반 for 루프의 주의사항

    1. 범위 기반 for 루프의 기본적인 사용은 읽기 전용입니다. 만약 컨테이너의 요소를 수정하고 싶다면, 참조 형식을 사용해야 합니다.

    for(auto &num : vec) {   // 요소를 참조로 받아옴
        num *= 2;  // vec의 모든 요소를 2배로 만듭니다.
    }

     

    2. 컨테이너 변경 주의: 루프 내에서 현재 순회 중인 컨테이너의 크기나 구조를 변경하는 연산을 주의해야 합니다

     

     

    nullptr

    C++11에서 도입된 nullptr는 포인터 리터럴의 새로운 타입입니다. nullptr는 모든 포인터 타입에 대해 사용할 수 있는 리터럴이며, 포인터가 가리키는 주소가 없음을 나타내기 위해 사용됩니다. 이는 C++에서 전통적으로 사용되던 NULL이나 숫자 0을 대체하기 위해 도입되었습니다.

     

    nullptr의 도입 배경

    전통적인 C++에서는 포인터를 초기화하지 않을 때, NULL이나 0을 사용하곤 했습니다. 하지만 이러한 방식은 다음과 같은 문제점들을 가지고 있었습니다:

    • 타입 안정성: NULL은 매크로로 정의되어 있어 실제로는 정수 타입입니다. 따라서 함수 오버로딩 등의 상황에서 예기치 않은 동작을 일으킬 수 있습니다.
    • 가독성: 0을 사용할 경우, 포인터의 초기화와 정수 0 사이의 구분이 불명확해질 수 있습니다.

    이러한 문제점들을 해결하기 위해 C++11에서는 명시적으로 포인터를 위한 nullptr를 도입하였습니다.

     

    nullptr 사용 예

    int* pi = nullptr;  // 정수 포인터 초기화
    void* pv = nullptr;  // void 포인터 초기화
    
    void func(int* ptr) {
        if (ptr == nullptr) {
            std::cout << "Pointer is null!" << std::endl;
        } else {
            std::cout << "Pointer is not null!" << std::endl;
        }
    }
    
    func(pi);  // 출력: Pointer is null!

     

    nullptr 주의사항

    • nullptr는 모든 포인터 타입과 호환될 수 있지만, 정수 타입과는 직접적으로 호환되지 않습니다. 따라서 정수 값으로의 변환을 시도할 때는 명시적인 캐스팅이 필요합니다.
    • C++11 이전의 코드와의 호환성을 위해 NULL도 여전히 사용할 수 있습니다. 그러나 새로운 코드를 작성할 때는 nullptr의 사용을 권장합니다.

     

     

    람다 식 (Lambda Expressions)

    C++11에서 도입된 람다 식은 이름 없는 인라인 함수를 정의하는 문법입니다. 함수 포인터나 함수 객체를 요구하는 곳에 간단하게 함수의 동작을 정의하고 사용하게 해줍니다.

     

    기본 문법

    람다 식의 기본 문법은 다음과 같습니다:

    [capture_clause](parameter_list) -> return_type { function_body }
    • capture_clause: 외부 변수를 람다 함수 내부로 "캡쳐"하는 방법을 정의합니다.
    • parameter_list: 함수의 매개변수 목록입니다.
    • return_type: 반환 타입을 지정합니다. (자동 추론 가능하므로 생략 가능)
    • function_body: 함수의 본문입니다.

     

    람다 사용 예제

    람다 식의 기본 문법은 다음과 같습니다:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    int main() {
        std::vector<int> numbers = {1, 2, 3, 4, 5};
    
        int value = 3;
        auto result = std::find_if(numbers.begin(), numbers.end(), [value](int num) {
            return num > value;
        });
    
        if (result != numbers.end()) {
            std::cout << *result << std::endl;  // 4 출력
        }
    
        return 0;
    }

     

    캡쳐 모드

    • []: 아무 것도 캡쳐하지 않습니다.
    • [=]: 모든 외부 변수를 값으로 캡쳐합니다.
    • [&]: 모든 외부 변수를 참조로 캡쳐합니다.
    • [a, &b]: 변수 a는 값으로, b는 참조로 캡쳐합니다.

     

    활용 방안

    람다는 다음과 같은 경우에 효율적으로 활용될 수 있습니다:

    • 알고리즘: STL 알고리즘에서 사용자 정의 동작을 정의할 때
    • 이벤트 핸들러: 이벤트 반응 방식을 직접 지정할 때
    • 임시 동작: 특정 동작을 일회성으로 정의하고 싶을 때

     

     

    댓글