맨위로가기

C++11

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

C++11은 2011년에 제정된 C++ 프로그래밍 언어의 개정 표준이다. 이 표준은 C++98과의 호환성을 유지하면서, 멀티스레딩 지원, 제네릭 프로그래밍 지원, 균일 초기화, 성능 향상 등 다양한 기능들을 추가했다. C++11은 런타임 성능 향상, 빌드 시간 성능 향상, 사용 편의성 향상, 새로운 기능 추가를 목표로 핵심 언어와 표준 라이브러리 모두를 확장했다. 주요 특징으로는 rvalue 참조와 이동 생성자, constexpr, POD 재정의, 초기화 리스트, 균일 초기화, 자료형 추론, 람다 함수 등이 있으며, 표준 라이브러리에는 스레딩 지원, 튜플, 해시 테이블, 정규 표현식, 스마트 포인터, 난수 생성 기능 등이 추가되었다. C와의 호환성 향상을 위해 C99의 일부 기능도 포함되었으며, 일부 기능은 제거되거나 더 이상 사용되지 않도록 변경되었다. C++11은 GCC, Visual Studio 등 다양한 컴파일러에서 지원되며, 한국 개발 환경에도 영향을 미쳤다.

더 읽어볼만한 페이지

  • 프로그래밍 언어 표준 - ISO/IEC JTC 1/SC 22
    ISO/IEC JTC 1/SC 22는 프로그래밍 언어, 환경 및 시스템 소프트웨어 인터페이스 분야의 표준화를 담당하는 ISO/IEC JTC 1의 하위 위원회이며, 다양한 프로그래밍 언어와 시스템 소프트웨어 인터페이스의 표준화를 목표로 1985년에 설립되었다.
  • 프로그래밍 언어 표준 - C99
    C99는 1999년 ISO/IEC 9899:1999로 출판된 C 프로그래밍 언어의 표준으로, 인라인 함수, 가변 길이 배열, `//` 주석 등 새로운 기능들을 추가하고 IEEE 부동소수점 자료 지원을 개선했으며 C90과 하위 호환성을 가지면서 C++와의 호환성을 고려했다.
  • C++ - 헤더 파일
    헤더 파일은 프로그래밍 언어에서 코드 재사용성, 모듈화, 컴파일 시간 단축에 기여하며 함수 프로토타입, 변수 선언 등을 포함하고 `#include` 지시어로 소스 코드에 포함되어 사용되는 파일이다.
  • C++ - 소멸자 (컴퓨터 프로그래밍)
    소멸자는 객체가 메모리에서 제거되기 직전에 호출되는 멤버 함수로, 객체 자원 해제 및 정리 작업을 수행하며, C++ 등 여러 언어에서 구현되고 메모리 누수 방지에 기여한다.
C++11
C++ 언어 버전 정보
이름C++11
다른 이름C++0x
표준ISO/IEC 14882:2011
개발 시작2000년대 초
최종 승인2011년 8월 12일
후속 버전C++14
주요 특징
핵심 목표기존 C++과의 호환성 유지
시스템 프로그래밍 및 임베디드 시스템 지원
새로운 프로그래밍 기술 지원 (예: 멀티스레딩, 제네릭 프로그래밍)
성능 향상
사용 편의성 증대
주요 변경 사항람다 표현식
R값 참조 (R-value reference)
이동 의미론 (Move semantics)
constexpr
auto 키워드
범위 기반 for 루프 (Range-based for loop)
초기화 목록 (Initializer list)
템플릿 별칭 (Template alias)
사용자 정의 리터럴 (User-defined literals)
noexcept 지정자
멀티스레딩 라이브러리
정규 표현식 라이브러리
스마트 포인터 (Smart pointer)
컴파일러 지원
지원 상태주요 컴파일러에서 대부분의 기능을 지원함 (Clang, GCC)

2. 표준 책정 방침

C++의 수정은 핵심 언어와 표준 라이브러리 모두를 포함한다.[2][3]

2011 표준안 개발에서 표준 위원회는 몇 가지 지침을 적용했다.[2][3]


  • C++98과의, 더 나아가 가능하다면 C와의 일관성 및 호환성을 유지한다.
  • 새로운 기능의 실현 방법으로, 코어 언어의 확장보다 표준 라이브러리의 확장을 우선시한다.
  • 프로그래밍의 기법을 발전시킬 수 있는 변경을 우선시한다.
  • 특정 애플리케이션에만 유효한 기능을 도입하기보다는, 시스템이나 라이브러리의 설계를 용이하게 하는 개선을 한다.
  • 기존의 타입 안전하지 않은 기법에 대해, 보다 안전한 대체 수단을 제공한다.
  • 하드웨어와 밀접하게 동작하는 능력과 효율을 향상시킨다.
  • 현실적인 문제에 대한 적절한 해결책을 마련한다.
  • “제로 오버헤드 원칙” (어떤 기능을 사용하기 위한 지원은, 그 기능을 사용하지 않을 경우 영향을 미치지 않는다)을 실천한다.
  • 상급자용 기능을 삭감하지 않고, C++의 학습과 지도가 쉬워지도록 한다.


초심자는 프로그래머 인구의 많은 부분을 차지한다. 또한, 많은 초심자는 자신이 습득한 일부 언어 기능에 구애되기 쉽고, 지식을 넓히려고 하지 않는다. 따라서, 초심자에 대한 배려는 중요하다고 여겨졌다. C++의 언어 사양의 크기 (애플리케이션이나 프로그래밍 스타일의 다양성 포함)를 고려하면, 아무리 오랜 경험을 가진 프로그래머도 새로운 프로그래밍 패러다임 앞에서는 미경험자가 될 수 있다는 점에서도 중요한 배려라고 할 수 있다.[2][3]

3. C++ 핵심 언어 확장

C++ 위원회는 언어 문법 개발에 주된 관심을 가졌으며, 이는 C++0x (C++11의 초기 명칭) 발표 일정에 영향을 주었다. C++11은 멀티태스킹 지원, 제네릭 프로그래밍 지원, 초기화 방법 통합, 성능 향상 등을 통해 언어의 문법적 범위를 크게 확장했다.

C++11의 핵심 언어 확장 및 변경 사항은 다음과 같이 분류할 수 있다.


  • 런타임 성능 향상: rvalue 참조 및 이동 생성자, constexpr
  • 빌드 시간 성능 향상: extern template, constexpr
  • 사용 편의성 향상: 초기화 리스트, 균일 초기화, 자료형 추론(auto, decltype), 범위 기반 for 반복문, 람다 함수와 람다 식, 함수 선언의 다른 방법, 객체 생성 향상, 명시된 가상함수 오버라이딩, 널 포인터 상수, 자료형에 안전한 enum, 템플릿의 괄호 처리, 형변환 연산자로써의 explicit, 템플릿 별명, union에 대한 제한 해제
  • 새로운 기능: 가변 템플릿, 새로운 문자열 리터럴, 사용자 정의 리터럴, 멀티태스킹 메모리 모델, TLS(스레드 로컬 저장소), 특수 멤버함수에 대해 기본값 사용 및 삭제에 대한 명시적 표시, long long int 자료형, 정적 assertion, 멤버에 대한 sizeof 허용


각 기능은 여러 범주에 해당될 수 있지만, 가장 적합한 범주에서 설명한다.

3. 1. 런타임 성능 향상

rvalue|rvalue영어 참조 및 이동 생성자는 C++11에서 도입된 기능으로, 불필요한 객체 복사를 줄여 런타임 성능을 향상시킨다. C++03에서는 임시 객체(주로 할당문의 오른쪽에 위치하는 rvalue)를 수정할 수 없었고, `const T&` 타입으로만 참조할 수 있었다. 그러나 C++11에서는 `T&&`로 표현되는 새로운 비 const 참조 타입이 추가되어, 초기화 후 수정 가능한 임시 객체를 참조할 수 있게 되었다.[10]

예를 들어, `std::vector`는 내부적으로 C 스타일 배열을 감싸는 래퍼이다. C++03에서는 `std::vector` 임시 객체가 생성되거나 함수에서 반환될 때, 새로운 `std::vector`를 생성하고 모든 rvalue의 데이터를 깊은 복사해야 했다. 그 후 임시 객체와 메모리는 파괴되었다. 이는 반환 값 최적화를 고려하지 않은 설명이다.

C++11에서는 `std::vector`에 대한 rvalue 참조를 받는 `std::vector`의 이동 생성자를 통해, 내부 C 스타일 배열에 대한 포인터를 rvalue에서 새 `std::vector`로 복사하고 rvalue 내부의 포인터를 null로 설정할 수 있다. 임시 객체는 더 이상 사용되지 않으므로 코드는 null 포인터에 접근하지 않으며, 포인터가 null이므로 범위를 벗어날 때 메모리가 삭제되지 않는다. 이는 깊은 복사 비용을 절약하고 안전하며 눈에 띄지 않는다.

Rvalue 참조는 표준 라이브러리 외부 변경 없이 기존 코드에 성능 이점을 제공한다. `std::vector` 임시 객체를 반환하는 함수의 반환 값 타입은 이동 생성자를 호출하기 위해 명시적으로 `std::vector &&`로 변경할 필요가 없다. 임시 객체는 자동으로 rvalue로 간주되기 때문이다. (단, `std::vector`가 이동 생성자가 없는 C++03 버전이라면 복사 생성자가 `const std::vector&`로 호출되어 상당한 메모리 할당이 발생한다.)

안전을 위해 몇 가지 제한이 있다. 명명된 변수는 rvalue 참조로 선언되었더라도 rvalue로 간주되지 않는다. rvalue를 얻으려면 함수 템플릿 `std::move()`를 사용해야 한다. Rvalue 참조는 특정 상황에서만 수정될 수 있으며, 주로 이동 생성자와 함께 사용하도록 의도되었다.

rvalue 참조와 lvalue 참조(일반 참조)에 대한 수정으로, 개발자는 rvalue 참조를 통해 완벽한 함수 전달을 제공할 수 있다. 가변 템플릿과 결합하면, 특정 인수를 사용하는 다른 함수에 인수를 완벽하게 전달할 수 있는 함수 템플릿을 허용한다. 이는 생성자 매개변수를 전달하여 해당 인수에 대해 올바른 생성자를 자동으로 호출하는 팩토리 함수를 생성하는 데 유용하다. C++ 표준 라이브러리 메서드의 [http://en.cppreference.com/w/cpp/container/vector/emplace_back emplace_back] 세트에서 볼 수 있다.

C++는 상수 표현식 개념을 가지고 있었다. `3+4`와 같은 표현식은 컴파일 타임과 런타임에서 항상 동일한 결과를 낸다. 상수 표현식은 컴파일러에게 최적화 기회를 제공하며, 컴파일러는 종종 컴파일 시간에 실행하여 결과를 프로그램에 하드 코딩한다. C++ 사양에서는 배열 정의, 열거자 값 등에 상수 표현식을 사용해야 한다.

그러나 상수 표현식은 함수 호출이나 객체 생성자를 포함할 수 없었다.



int get_five() {return 5;}

int some_value[get_five() + 7]; // 정수 12개의 배열을 생성합니다. 잘못된 C++



`get_five() + 7`이 상수 표현식이 아니기 때문에 C++03에서는 유효하지 않았다. C++03 컴파일러는 `get_five()`이 런타임에 상수인지 알 수 없었다.

C++11은 `constexpr` 키워드를 도입하여 함수나 객체 생성자가 컴파일 타임 상수임을 보장한다.[11]



constexpr int get_five() {return 5;}

int some_value[get_five() + 7]; // 정수 12개의 배열을 생성합니다. 유효한 C++11



이를 통해 컴파일러는 `get_five()`이 컴파일 타임 상수임을 이해하고 확인할 수 있다.

`constexpr` 함수에는 제한이 있다. void가 아닌 반환 유형이어야 하고, 함수 본문은 변수 선언, 새 유형 정의를 할 수 없으며, 선언, 널 문, 단일 return 문만 포함할 수 있다. 인수 대체를 수행한 후 return 문의 표현식이 상수 표현식을 생성하는 인수 값이 존재해야 한다.

C++11 이전에는 변수가 const로 선언되고 상수 표현식인 초기자를 가지며 정수 또는 열거형인 경우에만 변수 값을 상수 표현식에 사용할 수 있었다. C++11은 `constexpr` 키워드로 정의된 경우 변수가 정수 또는 열거형이어야 한다는 제한을 제거했다.



constexpr double earth_gravitational_acceleration = 9.8;

constexpr double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0;



이러한 데이터 변수는 암시적으로 const이며, 상수 표현식인 초기자를 가져야 한다.

사용자 정의 유형에서 상수 표현식 데이터 값을 생성하기 위해 생성자도 `constexpr`로 선언할 수 있다. `constexpr` 생성자의 함수 본문은 선언과 널 문만 포함할 수 있으며, `constexpr` 함수처럼 변수를 선언하거나 유형을 정의할 수 없다. 인수 대체를 수행한 후 상수 표현식으로 클래스 멤버를 초기화하는 인수 값이 존재해야 한다. 이러한 유형의 소멸자는 단순해야 한다.

`constexpr` 생성자가 있는 유형의 복사 생성자는 일반적으로 `constexpr` 함수에서 해당 유형의 객체를 값으로 반환할 수 있도록 `constexpr` 생성자로 정의되어야 한다. 복사 생성자, 연산자 오버로딩 등 클래스의 멤버 함수는 constexpr 함수의 요구 사항을 충족하는 한 `constexpr`로 선언될 수 있다. 이를 통해 컴파일러는 컴파일 시간에 객체를 복사하고 작업을 수행할 수 있다.

constexpr 함수 또는 생성자가 상수 표현식이 아닌 인수로 호출되면, 함수가 constexpr가 아닌 것처럼 호출이 동작하며 결과 값은 상수 표현식이 아니다. constexpr 함수의 return 문의 표현식이 특정 호출에 대해 상수 표현식으로 평가되지 않으면 결과는 상수 표현식이 아니다.

`constexpr`는 C++20에 도입된 `consteval`과 다르다. `consteval`은 항상 컴파일 타임 상수를 생성해야 하지만, `constexpr`는 이러한 제한이 없다.

3. 2. 빌드 시간 성능 향상

C++11에서는 `extern template` 선언을 통해 컴파일러가 특정 번역 단위에서 템플릿을 인스턴스화하지 않도록 지시할 수 있다. 다음은 그 예시이다.

```cpp

extern template class std::vector;

```

이는 여러 번역 단위에서 동일한 타입으로 템플릿이 인스턴스화되는 경우 컴파일 시간을 크게 줄일 수 있다.[1]

C++03에는 이미 상수 표현식(constant expression)이 존재했다. 상수 표현식은 `3 + 4`와 같이 항상 같은 결과를 반환하고 부작용이 없는 표현식이다. 컴파일러는 상수 표현식을 최적화하여 컴파일 시에 연산을 수행하고 프로그램에는 결과만 저장한다. 배열 정의나 열거형 값 지정 등 C++ 표준의 여러 부분에서 상수 표현식이 필요하다.[1]

하지만 함수 호출이나 객체 생성자는 상수 표현식이 아니었다. 예를 들어, 다음 코드는 C++03에서 허용되지 않는다.[1]



int GetFive() { return 5; }

int some_value[GetFive() + 5]; // C++03에서는 오류



`GetFive()` 함수는 런타임에 항상 5를 반환하지만, C++03 컴파일러는 이를 알 수 없었다. 함수가 전역 변수를 변경하거나 다른 함수를 호출하는 등 부작용이 있을 수 있다고 가정했기 때문이다.[1]

C++11에서는 `constexpr` 키워드를 도입하여 함수나 객체 생성자가 컴파일 시 상수임을 보장한다. 위 예제는 다음과 같이 수정할 수 있다.[1]



constexpr int GetFive() { return 5; }

int some_value[GetFive() + 5]; // C++11에서는 허용



`constexpr` 함수는 몇 가지 제약 조건이 있다. 함수는 `return` 문만 포함해야 하며, 반환값은 상수 표현식이어야 한다. 상수 표현식에서는 `constexpr`로 정의된 다른 함수를 호출하거나 상수 표현식 데이터 변수를 사용할 수 있다. 재귀 호출은 허용되지 않으며, `constexpr` 함수는 사용되기 전에 정의되어야 한다.[1]

`constexpr`을 사용하여 상수 표현식으로 변수를 정의할 수도 있다.[1]



constexpr double forceOfGravity = 9.8;

constexpr double moonGravity = forceOfGravity / 6;



`constexpr` 데이터 변수는 암묵적으로 `const`이다. 상수 표현식의 결과나 상수 표현식 생성자의 결과만 저장할 수 있다.[1]

사용자 정의 타입의 객체를 상수 표현식으로 만들려면 생성자를 `constexpr`로 선언해야 한다. `constexpr` 생성자는 본체가 비어 있어야 하고, 멤버 변수를 상수 표현식으로 초기화해야 한다. 소멸자는 자동으로 생성되어야 한다.[1]

`constexpr`로 생성된 객체의 복사본, 복사 생성자, 연산자 오버로드 등도 `constexpr`로 선언할 수 있다. 이를 통해 컴파일러는 컴파일 시에 객체 복사 등의 연산을 수행할 수 있다.[1]

`constexpr` 함수나 생성자는 `constexpr`이 아닌 인자로 호출할 수 있다. `constexpr` 리터럴을 `constexpr`이 아닌 변수에 할당할 수 있도록, `constexpr` 함수를 `constexpr`이 아닌 인자로 호출하고 그 결과를 `constexpr`이 아닌 변수에 저장할 수 있다. `constexpr` 키워드는 모든 내용이 `constexpr`인 경우 컴파일 시 상수성을 보장한다.[1]

3. 3. 사용 편의성 향상

C++11은 언어 사용 편의성을 크게 향상시키는 여러 기능들을 도입했다. 이러한 기능들은 타입 안전성을 개선하고, 코드 중복을 줄이며, 오류 발생 가능성을 낮추는 데 기여한다.

  • 초기화 리스트: C++03에서 상속받은 초기화 리스트(`{}`) 기능이 확장되었다. 구조체 뿐만 아니라 `std::vector`와 같은 표준 컨테이너를 포함한 모든 클래스에 초기화 리스트를 사용할 수 있게 되었다. 이는 `std::initializer_list` 템플릿을 통해 구현되었으며, 생성자와 다른 함수들이 초기화 리스트를 매개변수로 받을 수 있도록 한다.


```cpp

class SequenceClass

{

public:

SequenceClass(std::initializer_list list);

};

SequenceClass some_var = {1, 4, 5, 6};

```

`std::initializer_list`는 실제 타입이므로 클래스 생성자 외 다른 곳에서도 사용할 수 있다. 예를 들어, 일반 함수도 형식화된 `std::initializer_list`를 인수로 받을 수 있다.

```cpp

void function_name(std::initializer_list list);

function_name({1.0f, -3.45f, -0.4f});

```

  • 균일 초기화: C++03에는 형식을 초기화하는 여러 방법이 존재했고, 이들 간의 일관성이 부족했다. C++11은 모든 객체에서 작동하는 통일된 형식 초기화 구문을 제공한다. 이는 초기화 리스트 구문을 확장한 것이다.


```cpp

struct BasicStruct

{

int x;

double y;

};

struct AltStruct

{

AltStruct(int x, double y)

: x_{x}

, y_{y}

{

}

private:

int x_;

double y_;

};

BasicStruct var1{5, 3.2};

AltStruct var2{2, 4.3};

```

`var1`의 초기화는 집합체 초기화와 동일하게 동작하며, `var2`의 초기화는 생성자를 호출한다. 통일 초기화는 생성자 구문을 완전히 대체하지는 않지만, 보다 일관되고 편리한 초기화 방법을 제공한다.

  • 자료형 추론: C++03에서는 변수를 사용할 때 타입을 명시적으로 지정해야 했다. C++11에서는 `auto`와 `decltype` 키워드를 통해 컴파일러가 타입을 추론할 수 있게 되었다.

  • `auto`: 명시적 초기화를 사용하는 변수 정의에 사용되며, 초기화 값의 특정 타입의 변수를 생성한다.


```cpp

auto some_strange_callable_type = std::bind(&some_function, _2, _1, some_object);

auto other_variable = 5; // other_variable의 타입은 int

```

  • `decltype`: 컴파일 시간에 표현식의 타입을 결정하는 데 사용된다.


```cpp

int some_int;

decltype(some_int) other_integer_variable = 5;

```

`auto`와 `decltype`은 코드의 장황함을 줄이고, 템플릿 메타프로그래밍에서 유용하게 사용될 수 있다.

  • 범위기반 for 반복문: C++11은 범위 기반 `for` 반복문을 도입하여 요소 범위에 대한 반복을 쉽게 처리할 수 있도록 하였다.


```cpp

int my_array[5] = {1, 2, 3, 4, 5};

for (int& x : my_array) {

x *= 2;

}

```

이 형태의 `for`문은 C 스타일 배열, 초기화 리스트 및 반복자를 반환하는 `begin()` 및 `end()` 함수가 정의된 모든 유형에 대해 작동한다.

```cpp

[](int x, int y) -> int { return x + y; }

```

람다는 선택적으로 클로저가 될 수 있다.

  • 함수 선언의 다른 방법: C++11은 후행 반환 형식을 사용하는 새로운 함수 선언 구문을 도입했다.


```cpp

template

auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}

```

이 구문은 템플릿 함수 선언에서 반환 형식을 추론하는 데 유용하다.

  • 객체 생성의 향상: C++11에서는 생성자가 다른 생성자를 호출(위임)할 수 있게 되었고, 기반 클래스 생성자를 파생 클래스에서 상속할 수 있게 되었으며, 멤버 변수를 선언 시점에 초기화할 수 있게 되었다.

  • 명시된 가상함수 오버라이딩: C++11에서는 `override` 키워드를 사용하여 기반 클래스 함수를 의도치 않게 오버라이딩하는 실수를 방지할 수 있다. `override` 키워드는 컴파일러가 기반 클래스에 해당 시그니처를 가진 가상 함수가 있는지 확인하도록 한다.

  • 널 포인터 상수: C++11은 구별되는 널 포인터 상수로 작용할 새로운 키워드 `nullptr`를 도입했다. 이는 `nullptr_t` 타입이며, 모든 포인터 타입으로 암시적으로 변환 가능하다.

  • 자료형에 안전한 enum: C++11은 `enum class`를 도입하여 타입 안전한 열거형을 제공한다. `enum class` 값은 정수로 암시적으로 변환되지 않으며, 열거형 값은 해당 `enum class` 이름의 범위 내에 존재한다.

  • 템플릿의 괄호 처리: C++11에서는 파서가 여러 개의 오른쪽 꺾쇠 괄호(`>`)를 템플릿 인수 목록을 닫는 것으로 해석하도록 개선되었다.

  • 형변환 연산자로써의 explicit: C++11에서는 `explicit` 키워드를 변환 연산자에도 적용할 수 있게 되었다.

  • 템플릿 별명: C++11에서는 `using` 키워드를 사용하여 템플릿 별명을 생성할 수 있게 되었다.

  • union에 대한 제한 해제: C++11에서는 `union` 멤버에 대한 제한이 완화되어, 비자명 생성자 또는 소멸자를 가진 객체를 `union`에 포함할 수 있게 되었다.

3. 4. 새로운 기능

cpp

C++ 위원회는 언어 문법 개발에 주된 관심을 가졌다. C++0x의 발표 일정은 표준안에서 이 부분의 진행에 영향을 받았다. 언어의 문법적 범위는 멀티태스킹 지원, 제네릭 프로그래밍 지원, 초기화 방법 통합, 성능 향상 등으로 매우 증가하였다.

이 문서의 목적에 맞게, 문법적 기능과 변화는 "런타임 성능 향상", "컴파일 성능 향상", "편의성 향상", "새로운 기능" 등의 4부분으로 그룹화하였다. 일부 기능은 여러 부분에서 언급될 수 있지만, 주된 기능에 대해서 한 번씩만 설명할 것이다.

새로운 기능은 다음과 같다.

4. C++ 표준 라이브러리 확장

C++11 표준 라이브러리에는 여러 가지 새로운 기능이 도입되었다. 이 중 상당수는 이전 표준에서도 구현할 수 있었지만, 일부는 새로운 C++11 핵심 기능에 의존한다.

새로운 라이브러리의 상당 부분은 2005년에 발표된 C++ 표준 위원회의 라이브러리 기술 보고서(TR1)에서 정의되었다. TR1의 전체 및 부분 구현은 현재 `std::tr1` 네임스페이스를 사용하여 사용할 수 있다. C++11에서는 `std` 네임스페이스로 이동되었다. TR1 기능이 C++11 표준 라이브러리에 도입되면서, 초기 TR1 버전에서 사용할 수 없었던 C++11 언어 기능으로 업그레이드되었다.

C++11은 현재 존재하는 표준 라이브러리 구성 요소가 활용할 수 있는 다양한 새로운 언어 기능을 제공한다. 예를 들어, 대부분의 표준 라이브러리 컨테이너는 Rvalue 참조 기반 이동 생성자를 활용하여 컨테이너를 빠르게 이동시킬 수 있다. 표준 라이브러리 구성 요소는 적절한 경우 새로운 C++11 언어 기능으로 업그레이드되었으며, 여기에는 다음이 포함된다.


  • Rvalue 참조 및 관련 이동 지원
  • UTF-16 및 UTF-32 유니코드 문자 형식 지원
  • 가변 템플릿
  • 컴파일 시간 상수 표현식
  • `decltype`
  • `explicit` 변환 연산자
  • 기본값으로 선언되거나 삭제된 함수


표준 라이브러리를 사용하는 많은 코드가 작성되면서 개선이 필요한 부분이 드러났다. 고려된 많은 개선 사항 중에는 표준 라이브러리 할당자가 있었다. 이전 모델을 보완하기 위해 C++11에 할당자의 새로운 범위 기반 모델이 포함되었다.

C++03 언어는 스레딩을 지원하는 메모리 모델을 제공하지만, 실제로 스레딩을 사용하는 데 대한 주요 지원은 C++11 표준 라이브러리에서 제공된다.

새로운 스레드에서 실행할 함수 객체를 사용하는 `std::thread` 클래스가 제공된다. `std::thread::join()` 멤버 함수를 통해 스레드 조인 지원을 제공하여 다른 실행 스레드가 완료될 때까지 스레드가 정지하도록 할 수 있다. `std::thread::native_handle()` 멤버 함수를 통해 플랫폼별 작업을 위해 기본 네이티브 스레드 객체에 대한 액세스가 제공된다.

스레드 간의 동기화를 위해 적절한 뮤텍스조건 변수가 라이브러리에 추가되었다. 이러한 기능은 RAII 락 및 잠금 알고리즘을 통해 액세스할 수 있다.

고성능, 저수준 작업을 위해 뮤텍스의 오버헤드 없이 스레드 간 통신이 필요한 경우가 있다. 이는 메모리 위치에서 원자적 연산을 사용하여 수행된다. 명시적인 메모리 장벽도 이 목적으로 사용될 수 있다.

C++11 스레드 라이브러리는 또한 스레드 간에 비동기 결과를 전달하기 위한 미래와 약속과, 이러한 비동기 결과를 생성할 수 있는 함수 호출을 래핑하기 위한 `std::packaged_task`를 포함한다.

스레드 풀과 같은 더 높은 수준의 스레딩 기능은 향후 C++ 기술 보고서로 유보되었다.

새로운 `std::async` 기능은 작업을 실행하고 이를 `std::future`에 연결하는 편리한 방법을 제공한다. 사용자는 작업이 별도의 스레드에서 비동기적으로 실행되도록 할지 또는 값을 기다리는 스레드에서 동기적으로 실행되도록 할지를 선택할 수 있다.

튜플은 미리 정해진 크기를 가진, 서로 다른 타입의 객체들의 집합이다. 튜플은 구조체의 멤버 변수를 일반화한 것으로 간주될 수 있다.

C++11 버전의 TR1 튜플 타입은 가변 템플릿과 같은 C++11 기능의 이점을 활용했다.

가변 템플릿을 사용하여 튜플 클래스의 선언은 다음과 같다.

```cpp

template class tuple;

```

튜플 타입의 정의와 사용 예시:

```cpp

typedef std::tuple test_tuple;

long lengthy = 12;

test_tuple proof (18, 6.5, lengthy, "Ciao!");

lengthy = std::get<0>(proof); // 'lengthy'에 값 18 할당

std::get<3>(proof) = " Beautiful!"; // 튜플의 네 번째 요소 수정

```

`std::pair`에 대한 `std::make_pair`와 마찬가지로, 타입 추론을 사용하여 `std::tuple`을 자동으로 생성하는 `std::make_tuple`이 존재하며, `auto`는 그러한 튜플을 선언하는 데 도움이 된다. `std::tie`는 튜플을 언팩하는 데 도움이 되는 lvalue 참조의 튜플을 생성한다. `std::ignore` 또한 여기서 도움이 된다. 예를 들면 다음과 같다.

```cpp

auto record = std::make_tuple("Hari Ram", "New Delhi", 3.5, 'A');

std::string name ; float gpa ; char grade ;

std::tie(name, std::ignore, gpa, grade) = record ; // std::ignore는 장소 이름을 버리는 데 도움이 됩니다.

std::cout << name << ' ' << gpa << ' ' << grade << std::endl ;

```

관계 연산자를 사용할 수 있으며, 튜플의 특성을 확인하기 위해 두 개의 표현식을 사용할 수 있다(컴파일 중에만).

  • `std::tuple_size::value`는 튜플 `T`의 요소 수를 반환한다.
  • `std::tuple_element::type`은 튜플 `T`의 객체 번호 `I`의 타입을 반환한다.


C++ 표준 라이브러리에 해시 테이블(정렬되지 않은 연관 컨테이너)을 포함하는 것은 가장 반복적으로 요청되는 기능 중 하나였다. 해시 테이블은 최악의 경우 균형 트리보다 효율성이 떨어지지만, 많은 실제 애플리케이션에서 더 나은 성능을 보인다.

충돌은 ''분리 연결법''을 통해서만 관리된다. 자체 해시 테이블 구현을 개발한 비표준 라이브러리와의 이름 충돌을 피하기 위해 "hash" 대신 "unordered" 접두사를 사용했다.

새로운 라이브러리는 동일한 키를 가진 요소를 허용하는지 여부와 각 키를 연관된 값에 매핑하는지 여부에 따라 네 가지 유형의 해시 테이블을 가지고 있다.

해시 테이블 유형연관된 값동등한 키
`std::unordered_set`아니오아니오
`std::unordered_multiset`아니오
`std::unordered_map`아니오
`std::unordered_multimap`



새로운 클래스는 컨테이너 클래스의 모든 요구 사항을 충족하며, 요소에 접근하는 데 필요한 모든 메서드를 갖추고 있다.

이 새로운 기능은 C++ 언어 핵심 확장 기능이 필요하지 않았으며, 헤더 ``의 작은 확장과 헤더 `` 및 ``의 도입만 필요했다.

해시 테이블 외에도 두 개의 컨테이너가 표준 라이브러리에 추가되었다. `std::array`는 고정 크기 컨테이너이고, `std::forward_list`는 단일 연결 리스트이다.

새로운 헤더 ``에 정의된 새로운 라이브러리는 몇 가지 새로운 클래스로 구성된다.


  • 정규 표현식은 템플릿 클래스 `std::regex`의 인스턴스로 표현된다.
  • 발생은 템플릿 클래스 `std::match_results`의 인스턴스로 표현된다.
  • `std::regex_iterator`는 정규 표현식의 모든 일치 항목을 반복하는 데 사용된다.


함수 `std::regex_search`는 검색에 사용되며, '검색 및 바꾸기'의 경우 새 문자열을 반환하는 함수 `std::regex_replace`가 사용된다.[25]

다음은 `std::regex_iterator` 사용 예시이다.

```cpp

#include

const char *pattern = R"([^ ,.\t\n]+)"; // 공백, 쉼표, 마침표, 탭, 줄 바꿈으로 구분된 단어 찾기

std::regex rgx(pattern); // 잘못된 패턴 시 예외 발생

const char *target = "Unseen University - Ankh-Morpork";

// regex_iterator를 사용하여 'target'의 모든 단어를 'pattern'의 문자로 구분하여 식별합니다.

auto iter =

std::cregex_iterator(target, target + strlen(target), rgx);

// 시퀀스 종료 반복자를 만듭니다.

auto end =

std::cregex_iterator();

for (; iter != end; ++iter)

{

std::string match_str = iter->str();

std::cout << match_str << '\n';

}

```

C++11은 TR1의 `std::shared_ptr` 및 `std::weak_ptr`에 대한 개선 사항과 `std::unique_ptr`를 제공한다. `std::auto_ptr`은 더 이상 사용되지 않는다.

C 표준 라이브러리는 함수 `rand`를 통해 의사 난수를 생성하는 기능을 제공한다. C++11은 의사 난수를 생성하는 새로운 방법을 제공한다.

C++11의 난수 기능은 두 부분으로 나뉜다. 난수 생성기의 상태를 포함하고 의사 난수를 생성하는 생성기 엔진과 결과의 범위 및 수학적 분포를 결정하는 분포이다. 이 두 가지를 결합하여 난수 생성기 객체를 형성한다.

C 표준의 `rand`와 달리 C++11 메커니즘은 세 가지 기본 생성기 엔진 알고리즘과 함께 제공된다.

C++11은 또한 여러 표준 분포를 제공한다.

생성기와 분포는 이 예와 같이 결합된다.

```cpp

#include

#include

std::uniform_int_distribution distribution(0, 99);

std::mt19937 engine; // Mersenne twister MT19937

auto generator = std::bind(distribution, engine);

int random = generator(); // 0에서 99 사이의 균등 정수 변량을 생성합니다.

int random2 = distribution(engine); // 분포와 엔진 객체를 사용하여 다른 샘플을 직접 생성합니다.

```

래퍼 참조는 클래스 템플릿 `reference_wrapper`의 인스턴스에서 얻을 수 있다. 래퍼 참조는 C++ 언어의 일반적인 참조와 유사하다. 모든 객체로부터 래퍼 참조를 얻기 위해 함수 템플릿 `ref`가 사용된다 (상수 참조의 경우 `cref`가 사용된다).

래퍼 참조는 함수 템플릿에 유용하며, 복사본 대신 매개변수에 대한 참조가 필요하다.

```cpp

// 이 함수는 매개변수 'r'에 대한 참조를 받아 증가시킵니다.

void func (int &r) { r++; }

// 템플릿 함수.

template void g (F f, P t) { f(t); }

int main()

{

int i = 0;

g (func, i); // 'i'는 수정되지 않습니다.

std::cout << i << std::endl; // 출력 -> 0

g (func, std::ref(i)); // 'i'가 수정됩니다.

std::cout << i << std::endl; // 출력 -> 1

}

```

다형성 래퍼는 함수 객체에 대해 함수 포인터와 유사하지만, 덜 밀접하게 연결되어 있으며 래퍼의 인수와 호환되는 모든 호출 가능한 항목을 참조할 수 있다.

예제를 통해 특징을 명확히 할 수 있다.

```cpp

std::function func; // 'function' 템플릿 클래스를 사용하여 래퍼 생성.

std::plus add; // 'plus'는 'template T plus( T, T ) ;'로 선언됨.

func = add; // OK - 매개변수와 반환 타입이 동일함.

int a = func (1, 2); // 참고: 래퍼 'func'가 어떤 함수도 참조하지 않는 경우, 예외가 발생함.

std::function func2 ;

if (!func2)

{

// 'func2'에 아직 함수가 할당되지 않았으므로 참.

bool adjacent(long x, long y);

func2 = &adjacent; // OK - 매개변수와 반환 타입이 변환 가능함.

struct Test

{

bool operator()(short x, short y);

};

Test car;

func = std::ref(car); // 'std::ref'는 struct 'car'의 멤버 함수 'operator()'의 래퍼를 반환하는 템플릿 함수임.

}

func = func2; // OK - 매개변수와 반환 타입이 변환 가능함.

```

메타프로그래밍은 다른 프로그램(또는 자체)을 생성하거나 수정하는 프로그램을 만드는 것으로 구성된다. 이는 컴파일 중에 또는 실행 중에 발생할 수 있다. C++ 표준 위원회는 템플릿을 통해 컴파일 중에 메타프로그래밍을 위한 라이브러리를 도입하기로 결정했다.

다음은 C++03 표준을 사용하는 메타 프로그램의 예이다: 정수 지수를 계산하기 위한 템플릿 인스턴스의 재귀:

```cpp

template

struct Pow

{

// 재귀 호출 및 재조합.

enum{ value = B*Pow::value };

};

template< int B >

struct Pow

{

// ''N == 0'' 종료 조건.

enum{ value = 1 };

};

int quartic_of_three = Pow<3, 4>::value;

```

많은 알고리즘이 다양한 유형의 데이터에서 작동할 수 있다. C++의 템플릿은 제네릭 프로그래밍을 지원하며 코드를 더 간결하고 유용하게 만든다. 그럼에도 불구하고 알고리즘이 사용되는 데이터 유형에 대한 정보를 필요로 하는 경우가 많다. 이 정보는 '타입 트레이트'를 사용하여 템플릿 클래스의 인스턴스화 중에 추출할 수 있다.

'타입 트레이트'는 객체의 범주와 클래스(또는 구조체)의 모든 특성을 식별할 수 있다. 이는 새로운 헤더 ``에 정의되어 있다.

다음 예제에는 주어진 데이터 유형에 따라 두 개의 제안된 알고리즘 중 하나를 인스턴스화하는 템플릿 함수가 있다.

```cpp

// 작동하는 첫 번째 방법.

template< bool B > struct Algorithm

{

template static int do_it (T1 &, T2 &) { /*...*/ }

};

// 작동하는 두 번째 방법.

template<> struct Algorithm

{

template static int do_it (T1, T2) { /*...*/ }

};

// 'elaborate'를 인스턴스화하면 자동으로 올바른 작동 방식이 인스턴스화됩니다.

template

int elaborate (T1 A, T2 B)

{

// 'T1'이 정수이고 'T2'가 부동 소수점인 경우에만 두 번째 방법을 사용하고, 그렇지 않으면 첫 번째 방법을 사용합니다.

return Algorithm::value && std::is_floating_point::value>::do_it( A, B ) ;

}

```

헤더 ``에 정의된 '타입 트레이트'를 통해 타입 변환 연산을 생성하는 것도 가능하다.

템플릿 함수 객체의 반환 형식을 컴파일 시간에 결정하는 것은 직관적이지 않다. 특히 반환 값이 함수의 매개변수에 따라 달라지는 경우 더욱 그렇다.

TR1은 `std::result_of` 템플릿 클래스를 도입했고 C++11은 이를 채택했다. 이 클래스를 사용하면 모든 선언에 대해 함수 객체의 반환 유형을 결정하고 사용할 수 있다.

```cpp

template< class Obj >

class CalculusVer2

{

public:

template

typename std::result_of::type operator()(Arg& a) const

{

return member(a);

}

private:

Obj member;

};

```

`decltype`을 지원하기 위한 C++ 변경으로 인해 C++11 버전의 `std::result_of`는 더 이상 이러한 특수한 경우가 필요하지 않다. 구현은 모든 경우에 형식을 계산해야 한다.

5. C와의 호환성 향상

C99부터 C와의 호환성을 위해 다음과 같은 기능이 추가되었다.[26]


  • 전처리기:[27]
  • 가변 인자 매크로,
  • 인접한 좁은/넓은 문자열 리터럴의 연결,
  • `_Pragma()` – `#pragma`와 동일.
  • `long long` – 최소 64비트 길이의 정수형.
  • `__func__` – 자신이 속한 함수의 이름으로 평가되는 매크로.
  • 헤더:
  • `cstdbool` (`stdbool.h`),
  • `cstdint` (`stdint.h`),
  • `cinttypes` (`inttypes.h`).


C++03에서는 정수 상수 `0`에 정수 상수와 널 포인터라는 두 가지 역할이 부여되어 있었다. (이 동작은 C의 1972년부터 이어져 왔다).

오랫동안 프로그래머들은 `0` 대신 상수 `NULL`을 사용하여 이러한 잠재적 모호성을 어느 정도 피했다. 그러나 C++에서 이루어진 두 가지 설계 선택으로 인해 새로운 모호성이 발생했다. C에서는 `NULL`이 전처리기 매크로이며 `((void*)0)` 또는 `0`으로 확장되도록 정의되어 있다. C++에서는 `void*` 타입에서 다른 포인터 타입으로의 암시적 변환이 허용되지 않으므로 C의 첫 번째 정의와 같이 `NULL`을 정의하면 `char *c = NULL`과 같은 간단한 예에서도 컴파일 오류가 발생한다. 이를 수정하기 위해 C++에서는 `NULL`이 `0`으로 확장된다. `0`은 모든 포인터 타입으로의 변환이 특별히 허용된다. 이로 인해 오버로드 메커니즘과 심각한 상호 작용이 발생한다. 예를 들어, 다음과 같은 선언이 있고

```cpp

void foo(char *);

void foo(int);

```

`foo(NULL)`로 호출하는 경우 `foo(int)`가 호출된다. 이 동작은 대부분의 경우 의도된 것이 아니다.

새로운 표준에서는 널 포인터를 지정하기 위해 예약된 새로운 키워드 `nullptr`가 도입된다. `nullptr`는 정수형과의 비교 및 할당은 할 수 없지만, 모든 포인터 타입과의 비교 및 할당이 가능하다.

호환성을 위해 `0`의 현재 기능도 유지되지만, 이 새로운 구문이 잘 작동한다면 C++ 위원회는 `0`과 `NULL`을 널 포인터로 사용하는 것을 권장하지 않으며 의미의 중복을 제거할 것이다.

6. 제거되거나 더 이상 사용되지 않는 기능

시퀀스 포인트라는 용어가 제거되었으며, 대신 한 연산이 다른 연산보다 먼저 실행되거나 두 연산이 순서가 지정되지 않은 것으로 지정하는 것으로 대체되었다.[28]

키워드 export의 이전 사용법이 제거되었다.[29] 키워드 자체는 잠재적인 미래 사용을 위해 예약된 상태로 남아 있다.

동적 예외 지정은 더 이상 사용되지 않는다.[29] 예외를 발생시키지 않는 함수의 컴파일 타임 지정은 최적화에 유용한 noexcept 키워드를 사용하여 사용할 수 있다.

std::auto_ptr은 더 이상 사용되지 않으며, std::unique_ptr으로 대체되었다.

함수 객체 기본 클래스(std::unary_function, std::binary_function), 함수 포인터에 대한 어댑터, 멤버 포인터에 대한 어댑터 및 바인더 클래스는 모두 더 이상 사용되지 않는다.

7. 적용

C++11은 GCC 4.3부터 C++0x라는 이름으로,[36] 4.7부터는 C++11로서[37] 시험 적용되고 있고, Visual Studio 10[38]부터 Visual Studio 12[39]까지 부분적으로 적용되고 있다.

GCC(>=4.3)에서 커맨드 라인에 `-std=c++0x`를 추가하면 해당 컴파일러에서 지원하는 C++0x 표준으로 컴파일할 수 있다.[36] GCC 4.7 이상 버전에서는 `-std=c++11`과 `-std=gnu++11` 역시 지원한다.

참조

[1] 웹사이트 We have an international standard: C++0x is unanimously approved http://herbsutter.co[...] 2011-08-12
[2] 웹사이트 C++11 FAQ http://www.stroustru[...] 2014-10-15
[3] 웹사이트 C++11 Overview: What specific design goals guided the committee? https://isocpp.org/w[...] 2015-09-04
[4] 웹사이트 Bjarne Stroustrup: A C++0x overview https://www.research[...] 2011-06-30
[5] 웹사이트 ISO/IEC 14882:2011 http://www.iso.org/i[...] ISO 2011-09-02
[6] 웹사이트 Working Draft, Standard for Programming Language C++ http://www.open-std.[...] 2012-04-26
[7] 웹사이트 The Standard http://isocpp.org/st[...] 2012-11-02
[8] 웹사이트 Clang - C++ Programming Language Status https://clang.llvm.o[...] 2023-11-29
[9] 웹사이트 GCC 4.8.1 released, C++11 feature complete: Standard C++ https://isocpp.org/b[...] 2023-12-01
[10] 서적 C++ coding standards
[11] 웹사이트 General Constant Expressions for System Programming Languages, Proceedings SAC '10 http://www.stroustru[...] 2012-08-18
[12] 웹사이트 Decltype and auto, Programming Language C++, Document no: N1478=03-0061 http://www.open-std.[...] 2015-06-06
[13] 웹사이트 "Auto – A Necessary Evil?" Overload Journal #115 http://accu.org/inde[...] 2015-06-06
[14] 웹사이트 Document no: N1968=06-0038- Lambda expressions and closures for C++ http://www.open-std.[...] Open Standards 2009-04-20
[15] 웹사이트 Decltype (revision 5) http://www.open-std.[...] 2022-02-16
[16] 웹사이트 auto specifier (since C++11) - cppreference.com http://en.cppreferen[...] 2016-10-18
[17] 간행물 Introduce the nullptr constant - v1 http://www.open-std.[...] International Organization for Standardization 2020-04-19
[18] 웹사이트 N3448: Painless Digit Separation http://www.open-std.[...] 2012-09-21
[18] 웹사이트 N3499: Digit Separators http://www.open-std.[...] 2012-12-19
[19] 문서 '[[ISO/IEC 14882]]:2003(E): Programming Languages – C++ §3.2 One definition rule [basic.def.odr]'' para. 3' '[[International Organization for Standardization|ISO]]/[[International Electrotechnical Commission|IEC]]' 2003
[20] 웹사이트 Defaulted and Deleted Functions – ISO/IEC JTC1 SC22 WG21 N2210 = 07-0070 – 2007-03-11 http://www.open-std.[...] 2012-12-20
[21] 웹사이트 Using the GNU Compiler Collection (GCC): Long Long https://gcc.gnu.org/[...] 2016-07-25
[22] 웹사이트 Data Type Ranges (C++) http://msdn.microsof[...] 2009-04-23
[23] 서적 C – A Reference Manual
[24] 웹사이트 Broken promises–C++0x futures http://bartoszmilews[...] 2010-01-24
[25] 웹사이트 C++ Regular expressions library https://en.cpprefere[...] 2022-12-10
[26] 웹사이트 Clang - C++98, C++11, and C++14 Status http://clang.llvm.or[...] Clang.llvm.org 2013-06-10
[27] 웹사이트 Working draft changes for C99 preprocessor synchronization http://www.open-std.[...] 2014-05-26
[28] 웹사이트 Update on the C++-0x Language Standard http://blogs.msdn.co[...] 2010-05-25
[29] 웹사이트 Trip Report: March 2010 ISO C++ Standards Meeting http://herbsutter.co[...] 2010-03-24
[30] 웹사이트 範囲for文 - cpprefjp C++日本語リファレンス https://cpprefjp.git[...]
[31] 문서 ただし引数のみが違う場合に関しては、関数オーバーロードによる基底クラスのメンバーの隠蔽となり、通例コンパイラによって警告が出される。
[32] 웹사이트 std::invoke - cppreference.com https://ja.cpprefere[...]
[33] 웹인용 C++0x Initialization Lists http://video.google.[...] 2012-03-02
[34] 웹인용 We have an international standard: C++0x is unanimously approved http://herbsutter.co[...] 2011-08-12
[35] 웹인용 Bjarne Stroustrup: A C++0x overview http://www.research.[...] 2011-06-30
[36] 웹사이트 http://gcc.gnu.org/p[...]
[37] 웹사이트 http://gcc.gnu.org/g[...]
[38] 웹사이트 http://blogs.msdn.co[...]
[39] 웹사이트 http://blogs.msdn.co[...]



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com