9 분 소요

모던 C++ 은 현대적인 언어 특성에 발맞춰 좀더 단순하게 코딩할 수 있도록 개선되었습니다.(모던 C++ STL의 변경 내용은 [모던 C++ STL] 주요 구성 요소 미리보기를 참고하시기 바랍니다.)

  1. 이동 연산을 지원하여 런타임 성능을 향상시키고,
  2. 런타임에 했던 작업을 최대한 컴파일 타임으로 전환하여 런타임 성능을 향상시키며,
  3. 느슨했던 코딩 규약을 좀더 강화하고,
  4. 좀더 쉽게 코딩할 수 있도록 코딩 편의 기능들을 추가하였습니다.

  5. C++11

    런타임 성능 개선과 컴파일 타임 프로그래밍을 위해 많은 부분을 추가하였습니다. C++11 이전을 레거시 C++ 이라 하고, 이후를 모던 C++ 으로 구분할 만큼 많이 변했습니다. 특히 우측값 참조(&&)와 이동 생성자와 이동 대입 연산자, auto, 람다 표현식, constexpr은 혁신적인 변화라 할 수 있습니다.

    그외에 nullptr, char16_t, char32_t 타입, 사용자 정의 리터럴, 중괄호 초기화, 멤버 선언부 초기화, 범위 기반 for(), default, delete, override, final, 생성자 위임, 생성자 상속, 명시적 형변환, noexcept, decltype, 전달 참조, 완벽한 전달, 범위 있는 열거형, 무제한 공용체, static_assert(), 가변 템플릿 등 런타임 성능 개선과 컴파일 타임 프로그래밍, 코딩 계약 강화, 코딩 편의성을 위해 많은 부분이 추가되었습니다.

  6. C++14

    C++11에 추가된 내용을 일부 보강하였습니다. 특히 리턴 타입 추론으로 C++11 의 후행 리턴 개념을 깔끔하게 보강했고, constexpr 함수 제약을 완화하여 컴파일 타임 함수 작성 편의성이 향상됐습니다.

    그외에 변수 템플릿, decltype(auto), 비정적 멤버 변수의 멤버 선언부 초기화시 집합 초기화를 허용, [[deprecated]], 람다 캡쳐 초기화, 일반화된 람다 표현식, 이진 리터럴, 숫자 구분자가 추가되었습니다.

  7. C++17

    그동안 컴파일러에 의존했던 최적화 부분이 임시 구체화와 복사 생략 보증으로 표준화 되었고, if constexpr클래스 템플릿 인수 추론으로 컴파일 타임 프로그래밍을 좀더 강화 했으며, 초기식을 포함하는 if(), switch()구조화된 바인딩으로 컨테이너 관련 처리 코드가 깔끔해 졌습니다.

    그외에 인라인 변수, auto의 중괄호 초기화 특수 추론 규칙 개선, 열거형의 중괄호 직접 초기화 허용, 람다 캡쳐시 *this 를 이용, constexpr 람다 표현식, static_assert()의 메시지 생략, noexcept 함수 유형 포함, Fold 표현식, 비타입 템플릿 인자에서 auto 허용, u8’‘(문자) 리터럴, 16진수 부동 소수점 리터럴, [[fallthrough]], [[nodiscard]], [[maybe_unused]]가 추가되었습니다.

  8. C++20

    컨셉이 추가되어 코딩 계약이 강화되었고, 모듈로 컴파일 속도가 향상되었으며, 코루틴으로 함수의 일시 정지가 가능해 졌습니다. 또한 삼중 비교 연산자가 추가되어 비교 연산자 구현이 간단해 졌으며, 축약된 함수 템플릿으로 auto함수의 인자로 사용할 수 있고, 람다 표현식에서 템플릿 인자 지원으로 람다 표현식일반화 프로그래밍이 좀더 강화됐습니다. 그리고, 범위 기반 for()에서 초기식을 사용할 수 있어 반복문 작성이 좀더 쉬워졌습니다.

    그외에 컴파일 타임 프로그래밍(consteval 함수, constinit, constexpr 함수의 추가 제약 완화), 템플릿(비타입 템플릿 인자 규칙 완화, 클래스 템플릿 인수 추론시 initializer_list 개선), 타입과 리터럴(char8_t 타입, 정수에서 2의 보수 범위 보장), 람다 표현식(람다 캡쳐에서 파라메터 팩 지원, 람다 캡쳐에서 구조화된 바인딩 지원, 상태없는 람다 표현식의 기본 생성과 복사 대입 지원, 미평가 표현식에서도 람다 표현식 허용), explicit(bool), 인라인 네임스페이스와 단순한 중첩 네임스페이스 결합, 지명 초기화, 비트 필드 선언부 초기화, new[]에서 중괄호 집합 초기화로 배열 크기 추론, using enum, 비트 쉬프트 연산자의 기본 비트 표준화, __VA_OPT__, __has_cpp_attribute() 매크로 함수, 언어 지원 테스트, [[nodiscard]]의 생성자 지원, [[nodiscard(“이유”)]], [[likely]], [[unlikely]], [[no_unique_address]]가 추가되었습니다.

런타임 성능 개선

항목 내용
이동 연산 (C++11~)
완벽한 전달(C++11~)
(C++11~)
우측값 참조(&&)와 이동 생성자와 이동 대입 연산자가 추가되어 이동 연산을 지원하며, 임시 개체 대입시 속도가 향상되었습니다.
전달 참조가 추가되어 포워딩 함수에서도 효율적으로 함수 인자완벽하게 전달할 수 있습니다.
무제한 공용체 (C++11~) (C++11~)
무제한 공용체가 추가되어 공용체 멤버에서 생성자/소멸자/가상 함수 사용 제한이 풀렸으며, 메모리 절약을 위한 코딩 자유도가 높아졌습니다.
임시 구체화와 복사 생략 보증 (C++17~) (C++17~)
임시 구체화와 복사 생략 보증을 통해 컴파일러 의존적이었던 생성자 호출 및 함수 인수 전달 최적화, 리턴값 최적화등이 표준화 되었습니다.

컴파일 타임 프로그래밍

항목 내용
constexpr (C++11~) (C++11~)
constexpr이 추가되어 컴파일 타임 프로그래밍이 강화됐습니다.

(C++14~)
constexpr 함수의 제약이 완화되어 지역 변수, 2개 이상의 리턴문, if(), for(), while() 등을 사용할 수 있습니다.

(C++17~)
if constexpr이 추가되어 조건에 맞는 부분만 컴파일하고, 그렇지 않은 부분은 컴파일에서 제외할 수 있습니다.

(C++20~)
consteval 함수가 추가되어 컴파일 타임 함수로만 동작할 수 있습니다.
constinit가 추가되어 전역 변수, 정적 전역 변수, 정적 멤버 변수를 컴파일 타임에 초기화할 수 있습니다.
constexpr 함수 제약 완화가 한차례 더 보강되어 가상 함수, dynamic_cast, typeid(), 초기화되지 않은 지역 변수, try-catch(), 공용체 멤버 변수 활성 전환, asm등을 사용할 수 있습니다.
static_assert() (C++11~)
static_assert()가 추가되어 컴파일 타임 진단이 가능해 졌습니다.

(C++17~)
static_assert()의 메시지 생략을 지원합니다.
개선된 템플릿 (C++11~) (C++11~)
가변 템플릿파라메터 팩이 추가되어, 가변 인자(…)와 같이 갯수와 타입이 정해 지지 않은 템플릿 인자를 사용할 수 있습니다.
sizeof…() 연산자가 추가되어 가변 템플릿에서 파라메터 팩의 인자수를 구할 수 있습니다.
extern으로 템플릿 선언을 할 수 있으며, 템플릿 인스턴스 중복 생성을 없앨 수 있습니다.
템플릿 오른쪽 꺽쇠 괄호 파싱을 개선하여 템플릿 인스턴스화>가 중첩되어 >>와 같이 되더라도 공백을 추가할 필요가 없습니다.

(C++14~)
변수 템플릿이 추가되어 변수도 템플릿으로 만들 수 있습니다.

(C++17~)
클래스 템플릿 인수 추론이 추가되어 함수 템플릿처럼 템플릿 인스턴스화시 타입을 생략할 수 있습니다.
클래스 템플릿 인수 추론 사용자 정의 가이드가 추가되어 클래스 템플릿 인수 추론시 컴파일러에게 가이드를 줄 수 있습니다.
비타입 템플릿 인자에서 auto를 허용합니다.
Fold 표현식이 추가되어 가변 템플릿에서 파라메터 팩을 재귀적으로 반복하여 전개할 수 있습니다.

(C++20~)
축약된 함수 템플릿이 추가되어 함수 인자auto를 사용할 수 있습니다. 사실상 함수 템플릿의 간략한 표현입니다.
비타입 템플릿 인자 규칙이 완화되어 실수 타입과 리터럴 타입을 사용할 수 있습니다.
클래스 템플릿 인수 추론시 initializer_list인 경우가 개선되어 std::vector v_20{1, 2, 3};처럼 템플릿 인자를 명시하지 않아도 됩니다.
컨셉 (C++20~) (C++20~)
컨셉(concept)요구사항(requires)이 추가되어 템플릿 인자auto제약 조건(constraint)을 줄 수 있습니다.

코딩 계약 강화

항목 내용
개선된 타입과 리터럴 (C++11~) (C++11~)
타입 카테고리를 수립하여 컴파일 타임 프로그래밍이나 템플릿 메타 프로그래밍시의 코딩 계약을 강화할 수 있습니다.
using을 이용한 타입 별칭이 추가되어 typedef 보다 좀 더 직관적인 표현이 가능해 졌습니다.
nullptr 리터럴이 추가되어 좀더 타입에 안전한 코딩 계약이 가능해 졌습니다.
long long 타입이 추가되어 최소 8byte크기를 보장합니다.
ll, ull, LL, ULL 리터럴이 추가되어 long long용 정수형 상수를 제공합니다.
char16_t, char32_t 타입이 추가되어UTF-16 인코딩 문자와 UTF-32 인코딩 문자를 지원합니다.
u8””, u””, U””, u’‘(문자), U’‘(문자) 리터럴이 추가되어 유니코드를 지원하는 char16_t, char32_t 타입용 문자 상수를 제공합니다.
R”()”리터럴이 추가되어 개행이나 이스케이프 문자를 좀더 편하게 입력할 수 있습니다.
사용자 정의 리터럴이 추가되어 int operator ""_km(long double val);와 같이 사용자가 정의해서 사용할 수 있으며, 단위계 처리가 쉬워졌습니다.

(C++14~)
이진 리터럴이 추가되어 0b, 0B 접두어로 이진수 상수를 표현할 수 있습니다.
숫자 구분자가 추가되어 1'000'000와 같이 작은 따옴표(')를 숫자 사이에 선택적으로 넣을 수 있으며, 가독성이 좋아졌습니다.

(C++17~)
16진수 부동 소수점 리터럴이 추가되어 0xA.9p11과 같이 16진수로 실수를 표현할 수 있습니다.
u8’‘(문자) 리터럴이 추가되어 유니코드를 지원하는 1byte 크기의 문자 상수를 제공합니다.

(C++20~)
char8_t 타입이 추가되어 UTF-8 인코딩 문자를 지원합니다.
정수에서 2의 보수 범위를 보장합니다.
사용자 정의 리터럴 인자 규칙에 char8_t이 추가되었습니다.
noexcept (C++11~) (C++11~)
noexcept가 추가되어 함수의 예외 방출 여부를 보증하며, 소멸자는 기본적으로 noexcept로 동작합니다.
noexcept 연산자가 추가되어 해당 함수가 noexcept인지 컴파일 타임에 검사할 수 있습니다.

(C++17~)
noexcept가 함수 유형에 포함되어 예외 처리에 대한 코딩 계약을 좀더 단단하게 할 수 있습니다.
명시적 형변환 (C++11~) (C++11~)
explicit 형변환 연산자가 추가되어 명시적으로 형변환 할 수 있습니다.

(C++20~)
explicit(bool)이 추가되어 특정 조건일 때만 explicit로 동작하게 할 수 있습니다.
특성(attribute (C++11~) (C++11~)
attribute가 추가되어 컴파일러에게 부가 정보를 전달하는 방식을 표준화 했습니다.

(C++14~)
[[deprecated]]가 추가되어 소멸 예정인 것을 컴파일 경고로 알려줍니다.

(C++17~)
[[fallthrough]]가 추가되어 switch()에서 의도적으로 break를 생략하여 다음 case로 제어를 이동시킬때 발생하는 컴파일 경고를 차단할 수 있습니다.
[[nodiscard]]가 추가되어 리턴값을 무시하지 않도록 컴파일 경고를 해줍니다.
[[maybe_unused]]가 추가되어 사용되지 않은 개체의 컴파일 경고를 차단할 수 있습니다.
제조사 네임스페이스가 추가되어 [[msvc::noinline]] 와 같이 사용할 수 있습니다.

(C++20~)
[[nodiscard]]의 생성자 지원, [[nodiscard(“이유”)]]가 추가되었습니다.
[[likely]], [[unlikely]]가 추가되어 컴파일러에게 최적화 힌트를 줄 수 있습니다.
[[no_unique_address]]가 추가되어 아무 멤버 변수가 없는 개체의 크기를 최적화합니다.

코딩 편의성

항목 내용
개선된 네임스페이스 (C++11~) (C++11~)
인라인 네임스페이스가 추가되어 API 버전 구성이 편리해 졌습니다.

(C++14~)
단순한 중첩 네임스페이스가 추가되어 :: 로 표현할 수 있습니다.

(C++20~)
인라인 네임스페이스와 단순한 중첩 네임스페이스를 결합하여 표시할 수 있습니다.
개선된 초기화 (C++11~) (C++11~)
중괄호 초기화를 제공하여 클래스인지, 배열인지, 구조체인지 구분없이 중괄호({})를 이용하여 일관성 있게 초기화 할 수 있으며, 초기화 파싱 오류도 해결했습니다.
중괄호 복사 초기화로 함수 인수 전달, 리턴문 작성을 간소화할 수 있습니다.
중괄호 초기화시 인자의 암시적 형변환을 일부 차단하여, 코딩 계약이 개선되었습니다.
initializer_list가 추가되어 vector컨테이너의 초기 요소 추가가 간편해 졌습니다.
멤버 선언부 초기화가 추가되어 비정적 멤버 변수의 초기화가 쉬워졌습니다.

(C++14~)
비정적 멤버 변수의 멤버 선언부 초기화시 집합 초기화를 허용합니다.

(C++20~)
지명 초기화가 추가되어 중괄호 집합 초기화시 변수명을 지명하여 값을 초기화 할 수 있습니다.
비트 필드 선언부 초기화가 추가되었습니다.
new[]에서 중괄호 집합 초기화로 배열 크기 추론이 추가되어 배열 크기를 명시하지 않아도 됩니다.
개선된 제어문 (C++11~) (C++11~)
범위 기반 for()가 추가되어 컨테이너 요소의 탐색 처리가 쉬워졌습니다.

(C++17~)
초기식을 포함하는 if(), switch()가 추가되어 함수 리턴값을 평가하고 소멸하는 코드가 단순해 졌습니다.

(C++20~)
범위 기반 for()에서 초기식이 추가되었습니다.
개선된 클래스 (C++11~) (C++11~)
default, delete가 추가되어 암시적으로 생성되는 멤버 함수의 사용 여부를 좀더 명시적으로 정의할 수 있습니다.
override가 추가되어 가상 함수 오버라이딩의 코딩 규약이 좀더 단단해졌습니다.
final이 추가되어 가상 함수를 더이상 오버라이딩 못하게 할 수 있고, 강제적으로 상속을 제한할 수 있습니다.
생성자 위임이 추가되어 생성자초기화 리스트 코드가 좀더 간결해 졌습니다.
생성자 상속이 추가되어 부모 개체의 생성자상속받아 사용할 수 있어 자식 개체의 생성자 재정의 코드가 좀더 간결해 졌습니다.
멤버 함수 참조 지정자가 추가되어 멤버 함수&, &&좌측값에서 호출될때와 우측값에서 호출될 때를 구분하여 함수 오버로딩을 할 수 있습니다.
auto
decltype
후행 리턴 타입
(C++11~)
(C++11~)
autodecltype()이 추가되어 값으로부터 타입을 추론하며, 코딩이 간편해 졌습니다.
후행 리턴이 추가되어 함수 인자에 의존하여 리턴 타입을 결정하며, 좀더 동적인 함수 설계가 가능해 졌습니다.

(C++14~)
decltype(auto)가 추가되어 decltype()()내 표현식이 복잡할 경우 좀더 간결하게 작성할 수 있습니다.
리턴 타입 추론이 추가되어 후행 리턴 대신 autodecltype(auto)를 사용할 수 있습니다.

(C++17~)
auto의 중괄호 초기화 특수 추론 규칙 개선되어 auto a_11{1};initializer_list가 아니라 int 로 추론됩니다.
범위 있는 열거형 (C++11~) (C++11~)
범위 있는 열거형이 추가되어 이름 충돌 회피가 쉬워졌고, 암시적 형변환을 차단하며, 전방 선언도 지원합니다.

(C++17~)
열거형의 중괄호 직접 초기화를 허용하여 암시적 형변환을 차단하는 사용자 정의 열거형의 사용이 좀더 쉬워졌습니다.

(C++20~)
using enum이 추가되어 범위 있는 열거형의 이름 없이 열거자를 유효 범위내에서 사용할 수 있습니다.
람다 표현식, 클로저 (C++11~) (C++11~)
람다 표현식이 추가되어 1회용 익명 함수를 만들 수 있습니다.

(C++14~)
람다 캡쳐 초기화가 추가되어 람다 표현식내에서 사용하는 임의 변수를 정의하여 사용할 수 있습니다.
일반화된 람다 표현식이 추가되어 auto인자로 받아 마치 함수 템플릿처럼 사용할 수 있습니다.

(C++17~)
람다 캡쳐시 *this가 추가되어 개체 자체를 복제하여 사용할 수 있습니다.
constexpr 람다 표현식이 추가되어 람다 표현식도 컴파일 타임 함수로 만들 수 있습니다.

(C++20~)
람다 표현식에서 템플릿 인자를 지원합니다.
람다 캡쳐에서 파라메터 팩을 지원합니다.
람다 캡쳐에서 구조화된 바인딩을 지원합니다.
상태없는 람다 표현식의 기본 생성과 복사 대입을 지원합니다.
미평가 표현식에서도 람다 표현식을 허용하기 때문에 decltype()안에서 사용할 수 있습니다.
개선된 변수 (C++17~) (C++17~)
인라인 변수가 추가되어 헤더 파일에 정의된 변수를 여러개의 cpp에서 #include 하더라도 중복 정의 없이 사용할 수 있습니다. 또한, 클래스 정적 멤버 변수를 선언부에서 초기화 할 수 있습니다.
구조화된 바인딩 (C++17~) (C++17~)
구조화된 바인딩이 추가되어 배열, pair, tuple, 클래스등의 내부 요소나 멤버 변수에 쉽게 접근할 수 있습니다.
개선된 연산자 (C++20~) (C++20~)
삼중 비교 연산자가 추가되어 비교 연산자 구현이 간소화 되었습니다.
삼중 비교 연산자를 default로 정의할 수 있습니다.
비트 쉬프트 연산자의 기본 비트가 표준화되어 << 1는 곱하기 2의 효과가 있는 비트(즉, 0)로 채워지고, >> 1은 나누기 2의 효과가 있는 비트(즉, 양수면 0, 음수면 1)로 채워집니다.
모듈 (C++20~) (C++20~)
모듈이 추가되어 전처리 사용 방식을 개선하여 컴파일 속도를 향상시키고, #include 순서에 따른 종속성 문제, 선언과 정의 분리 구성의 불편함, 기호 충돌 문제를 해결했습니다.
코루틴 (C++20~)
코루틴이 추가되어 함수의 일시 정지 후 재개가 가능합니다.

기타

항목 내용
(C++11~) alignas() 와 alignof()가 추가되어 메모리 정렬 방식을 표준화 됐습니다.
가변 매크로가 추가되어 C언어와의 호환성이 높아졌습니다.
멤버의 sizeof()시 동작이 개선되어 개체를 인스턴스화 하지 않더라도 개체 멤버의 크기를 구할 수 있습니다.
(C++17~) __has_include가 추가되어 #include 하기 전에 파일이 존재하는지 확인할 수 있습니다.
(C++20~) __VA_OPT__가 추가되어 가변 인자가 있을 경우에는 괄호 안의 값으로 치환하고, 없을 경우에는 그냥 비워둡니다.
__has_cpp_attribute() 매크로 함수가 추가되어 C++11부터 추가된 특성(attirbute)이 지원되는지 확인 할 수 있습니다.
언어 지원 테스트 매크로가 추가되어 컴파일러가 C++11부터 추가된 언어 기능을 지원하는지 테스트 할 수 있습니다.

deprecate/remove

항목 내용
(~C++11) 동적 예외 사양deprecate 되었습니다. 예외를 나열하는 것보다 noexcept로 예외를 방출하느냐 안하느냐만 관심을 둡니다.
export 템플릿은 제대로 구현한 컴파일러는 드물고, 세부사항에 대한 의견이 일치하지 않아 C++11 부터 완전히 remove 되었습니다.
(~C++17) 동적 예외 사양 관련해서 throw()deprecate 되었습니다. 이제 noexcept만 사용해야 합니다.
&&, &=등이 특수기호가 없는 인코딩을 사용하는 곳을 위해 제공했던 trigraph가 remove되었습니다.(cppreference 참고)
변수를 CPU 레지스터에 배치하도록 힌트를 주는 register가 deprecate 되었습니다.
bool의 증감 연산이 deprecate 되었습니다.
(~C++20) 람다 캡쳐에서 [=] 사용시 this의 암시적 캡쳐가 deprecate되었으므로 명시적으로 작성해야 합니다.
volatile의 일부가 deprecate되었습니다.

태그:

카테고리:

업데이트:

댓글남기기