2.3 constexpr / noexcept

SeungHee Yun·2023년 11월 6일
0

전문가를 위한 C++

목록 보기
15/15

개요

C++의 바이블이라 할 수 있는 Effective C++에서는
가능하면 항상 constexpr을 사용하라 합니다.

지금으로서는 조금 어려운 개념일 수 있지만,
constexpr과 noexcept 키워드에 대해서 알아보도록 합시다.


constexpr

constexpr 키워드는 객체나 함수 앞에 붙일 수 있는 키워드로,
해당 객체나 함수의 리턴 값을 컴파일 타임에 알 수 있다는 의미입니다.

    int arr[size];
    //-------------------------------------------------//
    template<int N>
    struct A
    {
        int operator()() { return N; }
    };
    A<number> a;
    //-------------------------------------------------//
    enum A { a = number, b, c };

위 코드 단락이 컴파일 되기 위해서는

배열의 size, template의 number, enum의 number가
정수 상수식 이여야합니다.

constexpr은 앞서 말한 대로,
어떠한 식이 상수식이라 명시해주는 키워드입니다.

C++11에서 constexpr이 도입되었을 때는, 여러 제약이 많았습니다.

예를 들어, 함수 내부에서 변수들을 정의할 수 없고
return 문은 딱 하나만 있어야 했습니다.

하지만 C++14부터 위와 같은 제약 조건들이 완화되어
아래와 같은 제약 조건들 빼고는 모두
constexpr 함수 내부에서 수행할 수 있습니다.

* goto 문 사용
* 예외처리(try문;C++20부터 사용가능)
* 리터럴 타입이 아닌 변수의 정의
* 초기화되지 않는 변수의 정의
* 실행 중간에 constexpr이 아닌 함수의 호출

만일 조건을 만족하지 않는 작업을 함수 내에서 하면
컴파일 오류가 발생합니다.

예를 들어, 배열의 크기, 루프 횟수,
컴파일 타임에서 결정되어야 하는 상수 등을 constexpr로 선언하면,

런타임에서 값이 변경되지 않고 컴파일 타임에 결정되는 것을 보장
할 수 있습니다.

이러한 이점은 코드의 성능과 안정성을 향상시킵니다.

    constexpr int Square(int x) 
    {
        return x * x;
    }

    int main() 
    {
        constexpr int sideLength = 5;
        int area = Square(sideLength);  // 컴파일 타임에 area의 값이 결정됨
        return 0;
    }

위 코드에서 Square는 constexpr로 선언되었으므로,
area 값은 컴파일 타임에 결정됩니다.


noexcept

만약 어떤 함수가 예외를 발생시키지 않는다면
noexcept 키워드를 통해 명시할 수 있습니다.

#include <iostream>

using namespace std;

int foo() noexcept { return 0; }

int bar() noexcept { throw 1; }

int main()
{
	foo();

	try
	{
		bar();
	}
	catch (int x)
	{
		std::cout << "Error : " << x << std::endl;
	}

	return 0;
}

컴파일러는 noexcept 키워드가 붙은 함수를
예외를 발생시키지 않는다 판단한 후 컴파일 합니다.

noexcept로 명시된 함수가 예외를 발생시켜도,
예외는 처리되지 않고 프로그램은 종료됩니다.

C++11부터 소멸자들은 기본적으로 noexcept 입니다.
절대로 소멸자에서 예외를 던지면 안되기 때문입니다.


참고 : 코덕 개발자 노트


profile
Enthusiastic Game Developer

0개의 댓글