WHAT’S NEW IN C++11
Blue Wind
백정상
C++11
C++0x 로 알려짐
2011년 8월에 표준으로 선정
CONTENTS
퍼포먼스 향상
언어 사용성 강화
언어 기능 강화
c++ standard libraries 변경
불필요한 복사/생성 방지

퍼포먼스 향상
R-VALUE REFERENCES
l-value
수식의 왼쪽에 있는 값
일반적으로 대입되는 값
r-value
수식의 오른쪽에 있는 값
일반적으로 대입하는 값
r-value reference
말 그래도 r-value의 레퍼런스
왜 필요한가
l-value reference는 익숙히 사용하고 있었다
큰 데이터를 패러미터로 넘길 때 포인터보다 좀 더 안전하게 레퍼런스를 이용
그럼 큰 데이터를 반환해야 할 때엔?
기존에는 컴파일러에서 최적화 해주는 수준으로 커버
C++11은 move semantic을 도입
의미 없는 복사 / 생성을 최적화
이를 위해서 반환해야 할 값의 레퍼런스(r-value reference)가 필요하다
예제
std::vector<int> MakeVector() {
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
return vec;
}

std::vector<int> vec2 = MakeVector();
기존의 벡터 복사 생성자

vec
카피
vec2
새로 할당 된 메모리
R-VALUE REF를 이용해 반환하는 과정

vec

vec3

null
R-VALUE REF를 이용해 반환하는 과정

vec

vec3

null
이를 위해서
C++11은 이를 위해 두 가지 방식의 생성자를 지원
copy constructor
vector::vector(const vector<T>&v)
move constructor
vector::vector(vector<T>&& v)
대입 연산자도 비슷하게 두 가지를 지원
변수에서 R-VALUE를 얻어야 할 때
std::move()를 사용해서 r-value를 전달

class A {
A(A&& a) {
this->s = std::move(a.s);
}
private:
HugeBigObj s;
}
GENERALIZED CONSTANT EXPRESSIONS
기존에는 상수 연산이 없고 상수만 사용할 수 있었음
코드 내에 잦은 상수연산은 컴파일러 퍼포먼스를 저하시켰음
C++11에는 상수 연산 키워드가 추가

int get_five() {return 5;}
int some_value[get_five() + 7]; // 컴파일 에러

constexpr int get_five() {return 5;}
int some_value[get_five() + 7]; // 12개의 정수 배열이 만들어짐
INITIALIZER LIST
POD나 스탠다드 컨테이너의 초기 변수를 리스트 형태로 전달 가능

std::vector<std::string> v = {“aaa”, “bbb”, “ccc”, “ddd”};
std::vector<std::string> v({“aaa”, “bbb”, “ccc”, “ccc”});
std::vector<std::string> v{“aaa”, “bbb”, “ccc”, “ddd”};

// Uniform initialization
UNIFORM INITIALIZATION
모든 초기화 과정이 {var1, var2, … varn} 형태로 통합하여 사용이 가능
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};
불편했던 부분을 개선

언어 사용성 강화
TYPE INFERENCE
타입을 추론해서 선언이 가능

auto itr = m_map.find(10);

//std::map<int, string>::iterator itr = m_map.find(10);

auto intValue = 5;
auto fValue = 5.0f;
auto로 선언된 변수랑 같은 타입으로 선언하는 법
const decltype(itr) end = m_map.end();
decltype(intValue) intValue2 = 10;
RANGE-BASED FOR LOOP
모든 시퀀스 컨테이너의 range에 따라 아이템 순회가 가능해짐
int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
x *= 2;
}
std::vector<int> numList = {1,2,3,4,5};
for (int &num : numList) {
cout << “num: “ << num * 2;

}
LAMBDA FUNCTIONS
[capture](parameters)->return-type{body}
간단한 익명 함수 처리가 가능해짐
다양한 방식으로 사용이 가능
CPS 코딩이 편해짐
자세한 용례는 http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B 참고
LAMBDA 예제
std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
std::for_each(begin(some_list), end(some_list), [&total](int x) {
total += x;
});
OBJECT CONSTRUCTION IMPROVEMENTS
생성자에서 다른 생성자를 호출 가능해짐

class SomeType {
int number;

public:
SomeType(int new_number) : number(new_number) {}
SomeType() : SomeType(42) {}
};
OBJECT CONSTRUCTION IMPROVEMENTS
베이스 클래스 생성자 상속이 가능하고 어떤 생성자를 상속받을지 설정 가능
class BaseClass {
public:
BaseClass(int value);
};

class DerivedClass : public BaseClass {
public:
using BaseClass::BaseClass;
};
EXPLICIT OVERRIDE AND FINAL
struct Base {
virtual void some_func(float);
};

struct Derived : Base {
virtual void some_func(int);
};
실수로 시그니처가 달라지면 virtual function이 2개 만들어지는 문제가 있었음
EXPLICIT OVERRIDE AND FINAL
struct Base {
virtual void some_func(float);
};

struct Derived : Base {
virtual void some_func(int) override; //베이스 클래스와 시그니처가 맞지 않으면 에러를 표시
};
걍 오버라이드 할 때엔 무조건 뒤에 붙이시면 됩니다
EXPLICIT OVERRIDE AND FINAL
final 키워드로 상속이나 오버라이드를 더 이상 못하게 막을 수 있음
struct Base1 final { };
struct Derived1 : Base1 { }; // Base1 클래스가 final 선언되었으므로 에러

struct Base2 {
virtual void f() final;
};
struct Derived2 : Base2 {
void f(); //가상함수 Base2::f가 final 처리 되었으므로 에러
};
NULL POINTER CONSTANT
nullptr 상수가 만들어짐

char *pc = nullptr; //OK
bool b = nullptr

//OK. b is false

int a = nullptr;

//error
STRONGLY TYPED ENUMERATIONS
enum에 이름과 타입 설정이 불가능해서 예전엔 이런 꼼수를 썼음
namespace Enumeration {
enum {
A,
B,
C

}
typedef int type;
}

Enumeration::type a = Enumeration::A;
STRONGLY TYPED ENUMERATIONS
이젠 타입과 이름 설정이 가능
enum class Enumeration : unsigned int {
Val1,
Val2,
Val3 = 100,
Val4 // = 101
};
RIGHT ANGLE BRAKET
옛날에는 컴파일러가 템플릿 키워드 중첩해서 쓴 것과 << 연산자랑 헷갈렸음
이젠 컴파일러가 알아서 잘 해석해줌
안 되던 게 됩니다

언어 기능 강화
VARIADIC TEMPLATES
템플릿 패러미터를 가변적으로 받을 수 있게 변경됨
이거 덕분에 템플릿 메타 프로그래밍 할 때 패러미터 개수 문제로 골머리 썩던 게 해결
자세한 내용은 http://en.wikipedia.org/wiki/Variadic_templates 참고
NEW STRING LITERALS
문자 인코딩 타입을 정할 수 있게 되었다
u8"I'm a UTF-8 string."
u"This is a UTF-16 string."
U"This is a UTF-32 string.“
R”*(This is a “raw” string)*”
이 때문에 새로운 캐릭터 타입이 추가됨
char16_t
char32_t
MULTITHREADING MEMORY MODEL
C++11 에 멀티스레드 라이브러리가 추가 됨
관련해서 메모리 모델 추가 됨
Memory ordering
Memory barrier
Consistency model
Shared memory
LONG LONG INT
드디어 64비트 정수가 표준화 됨
그 전에는 컴파일러들이 그냥 지원하는 거였음
STATIC ASSERTIONS
컴파일 타임에 걸 수 있는 assertion이 생김
주로 전처리 지시자나 템플릿 사용등을 검사

static_assert((GREEKPI > 3.14) && (GREEKPI < 3.15), "GREEKPI is inaccurate!");
언어가 바뀌었으니 표준 라이브러리도 바뀌었겠죠?

표준 라이브러리 변경
기존 라이브러리에 C++11 적용
적용 된 기능들
Rvalue reference 와 move constructor
UTF-16, UTF-32
Variadic templates
auto, decltype
explicit conversion operators
default/deleted functions
THREADING FACILITIES
앞서 얘기한대로 스레딩 관련 컴포넌트들 추가
std::thread, std::mutex, std::recursive_mutex
std::future, std::promise, std::async
etc.
thread_pool은 아직 안 들어감
NEW CONTAINERS
Tuple
std::tuple
Hash tables
std::unordered_set
std::unordered_map
std::unordered_multiset
std::unordered_multimap
REGULAR EXPRESSION
드디어 C++에 정규표현식이 들어갔습니다!
std::regex, std::regex_search, std::match_results etc.
SMART POINTERS
스마트 포인터가 추가됨
std::unique_ptr

// ownership을 1개로 제한

std::shared_ptr

// 공유 포인터

std::weak_ptr

// 공유 포인터의 상호참조를 방지하고 싶을 때

std::auto_ptr

// 메모리 자동 해지 포인터. ownership 문제가 있음
그 외에 다루지 않은 부분은
C++11 표준 문서나 위키피디아를 참고하시면 됩니다
참고
Wikipedia : http://en.wikipedia.org/wiki/C%2B%2B11
rein.kr : http://rein.kr/blog/archives/2371

What’s new in c++11

  • 1.
    WHAT’S NEW INC++11 Blue Wind 백정상
  • 2.
    C++11 C++0x 로 알려짐 2011년8월에 표준으로 선정
  • 3.
    CONTENTS 퍼포먼스 향상 언어 사용성강화 언어 기능 강화 c++ standard libraries 변경
  • 4.
  • 5.
    R-VALUE REFERENCES l-value 수식의 왼쪽에있는 값 일반적으로 대입되는 값 r-value 수식의 오른쪽에 있는 값 일반적으로 대입하는 값 r-value reference 말 그래도 r-value의 레퍼런스
  • 6.
    왜 필요한가 l-value reference는익숙히 사용하고 있었다 큰 데이터를 패러미터로 넘길 때 포인터보다 좀 더 안전하게 레퍼런스를 이용 그럼 큰 데이터를 반환해야 할 때엔? 기존에는 컴파일러에서 최적화 해주는 수준으로 커버 C++11은 move semantic을 도입 의미 없는 복사 / 생성을 최적화 이를 위해서 반환해야 할 값의 레퍼런스(r-value reference)가 필요하다
  • 7.
    예제 std::vector<int> MakeVector() { std::vector<int>vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); return vec; } std::vector<int> vec2 = MakeVector();
  • 8.
    기존의 벡터 복사생성자 vec 카피 vec2 새로 할당 된 메모리
  • 9.
    R-VALUE REF를 이용해반환하는 과정 vec vec3 null
  • 10.
    R-VALUE REF를 이용해반환하는 과정 vec vec3 null
  • 11.
    이를 위해서 C++11은 이를위해 두 가지 방식의 생성자를 지원 copy constructor vector::vector(const vector<T>&v) move constructor vector::vector(vector<T>&& v) 대입 연산자도 비슷하게 두 가지를 지원
  • 12.
    변수에서 R-VALUE를 얻어야할 때 std::move()를 사용해서 r-value를 전달 class A { A(A&& a) { this->s = std::move(a.s); } private: HugeBigObj s; }
  • 13.
    GENERALIZED CONSTANT EXPRESSIONS 기존에는상수 연산이 없고 상수만 사용할 수 있었음 코드 내에 잦은 상수연산은 컴파일러 퍼포먼스를 저하시켰음 C++11에는 상수 연산 키워드가 추가 int get_five() {return 5;} int some_value[get_five() + 7]; // 컴파일 에러 constexpr int get_five() {return 5;} int some_value[get_five() + 7]; // 12개의 정수 배열이 만들어짐
  • 14.
    INITIALIZER LIST POD나 스탠다드컨테이너의 초기 변수를 리스트 형태로 전달 가능 std::vector<std::string> v = {“aaa”, “bbb”, “ccc”, “ddd”}; std::vector<std::string> v({“aaa”, “bbb”, “ccc”, “ccc”}); std::vector<std::string> v{“aaa”, “bbb”, “ccc”, “ddd”}; // Uniform initialization
  • 15.
    UNIFORM INITIALIZATION 모든 초기화과정이 {var1, var2, … varn} 형태로 통합하여 사용이 가능 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};
  • 16.
  • 17.
    TYPE INFERENCE 타입을 추론해서선언이 가능 auto itr = m_map.find(10); //std::map<int, string>::iterator itr = m_map.find(10); auto intValue = 5; auto fValue = 5.0f; auto로 선언된 변수랑 같은 타입으로 선언하는 법 const decltype(itr) end = m_map.end(); decltype(intValue) intValue2 = 10;
  • 18.
    RANGE-BASED FOR LOOP 모든시퀀스 컨테이너의 range에 따라 아이템 순회가 가능해짐 int my_array[5] = {1, 2, 3, 4, 5}; for (int &x : my_array) { x *= 2; } std::vector<int> numList = {1,2,3,4,5}; for (int &num : numList) { cout << “num: “ << num * 2; }
  • 19.
    LAMBDA FUNCTIONS [capture](parameters)->return-type{body} 간단한 익명함수 처리가 가능해짐 다양한 방식으로 사용이 가능 CPS 코딩이 편해짐 자세한 용례는 http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B 참고
  • 20.
    LAMBDA 예제 std::vector<int> some_list{1, 2, 3, 4, 5 }; int total = 0; std::for_each(begin(some_list), end(some_list), [&total](int x) { total += x; });
  • 21.
    OBJECT CONSTRUCTION IMPROVEMENTS 생성자에서다른 생성자를 호출 가능해짐 class SomeType { int number; public: SomeType(int new_number) : number(new_number) {} SomeType() : SomeType(42) {} };
  • 22.
    OBJECT CONSTRUCTION IMPROVEMENTS 베이스클래스 생성자 상속이 가능하고 어떤 생성자를 상속받을지 설정 가능 class BaseClass { public: BaseClass(int value); }; class DerivedClass : public BaseClass { public: using BaseClass::BaseClass; };
  • 23.
    EXPLICIT OVERRIDE ANDFINAL struct Base { virtual void some_func(float); }; struct Derived : Base { virtual void some_func(int); }; 실수로 시그니처가 달라지면 virtual function이 2개 만들어지는 문제가 있었음
  • 24.
    EXPLICIT OVERRIDE ANDFINAL struct Base { virtual void some_func(float); }; struct Derived : Base { virtual void some_func(int) override; //베이스 클래스와 시그니처가 맞지 않으면 에러를 표시 }; 걍 오버라이드 할 때엔 무조건 뒤에 붙이시면 됩니다
  • 25.
    EXPLICIT OVERRIDE ANDFINAL final 키워드로 상속이나 오버라이드를 더 이상 못하게 막을 수 있음 struct Base1 final { }; struct Derived1 : Base1 { }; // Base1 클래스가 final 선언되었으므로 에러 struct Base2 { virtual void f() final; }; struct Derived2 : Base2 { void f(); //가상함수 Base2::f가 final 처리 되었으므로 에러 };
  • 26.
    NULL POINTER CONSTANT nullptr상수가 만들어짐 char *pc = nullptr; //OK bool b = nullptr //OK. b is false int a = nullptr; //error
  • 27.
    STRONGLY TYPED ENUMERATIONS enum에이름과 타입 설정이 불가능해서 예전엔 이런 꼼수를 썼음 namespace Enumeration { enum { A, B, C } typedef int type; } Enumeration::type a = Enumeration::A;
  • 28.
    STRONGLY TYPED ENUMERATIONS 이젠타입과 이름 설정이 가능 enum class Enumeration : unsigned int { Val1, Val2, Val3 = 100, Val4 // = 101 };
  • 29.
    RIGHT ANGLE BRAKET 옛날에는컴파일러가 템플릿 키워드 중첩해서 쓴 것과 << 연산자랑 헷갈렸음 이젠 컴파일러가 알아서 잘 해석해줌
  • 30.
    안 되던 게됩니다 언어 기능 강화
  • 31.
    VARIADIC TEMPLATES 템플릿 패러미터를가변적으로 받을 수 있게 변경됨 이거 덕분에 템플릿 메타 프로그래밍 할 때 패러미터 개수 문제로 골머리 썩던 게 해결 자세한 내용은 http://en.wikipedia.org/wiki/Variadic_templates 참고
  • 32.
    NEW STRING LITERALS 문자인코딩 타입을 정할 수 있게 되었다 u8"I'm a UTF-8 string." u"This is a UTF-16 string." U"This is a UTF-32 string.“ R”*(This is a “raw” string)*” 이 때문에 새로운 캐릭터 타입이 추가됨 char16_t char32_t
  • 33.
    MULTITHREADING MEMORY MODEL C++11에 멀티스레드 라이브러리가 추가 됨 관련해서 메모리 모델 추가 됨 Memory ordering Memory barrier Consistency model Shared memory
  • 34.
    LONG LONG INT 드디어64비트 정수가 표준화 됨 그 전에는 컴파일러들이 그냥 지원하는 거였음
  • 35.
    STATIC ASSERTIONS 컴파일 타임에걸 수 있는 assertion이 생김 주로 전처리 지시자나 템플릿 사용등을 검사 static_assert((GREEKPI > 3.14) && (GREEKPI < 3.15), "GREEKPI is inaccurate!");
  • 36.
    언어가 바뀌었으니 표준라이브러리도 바뀌었겠죠? 표준 라이브러리 변경
  • 37.
    기존 라이브러리에 C++11적용 적용 된 기능들 Rvalue reference 와 move constructor UTF-16, UTF-32 Variadic templates auto, decltype explicit conversion operators default/deleted functions
  • 38.
    THREADING FACILITIES 앞서 얘기한대로스레딩 관련 컴포넌트들 추가 std::thread, std::mutex, std::recursive_mutex std::future, std::promise, std::async etc. thread_pool은 아직 안 들어감
  • 39.
  • 40.
    REGULAR EXPRESSION 드디어 C++에정규표현식이 들어갔습니다! std::regex, std::regex_search, std::match_results etc.
  • 41.
    SMART POINTERS 스마트 포인터가추가됨 std::unique_ptr // ownership을 1개로 제한 std::shared_ptr // 공유 포인터 std::weak_ptr // 공유 포인터의 상호참조를 방지하고 싶을 때 std::auto_ptr // 메모리 자동 해지 포인터. ownership 문제가 있음
  • 42.
    그 외에 다루지않은 부분은 C++11 표준 문서나 위키피디아를 참고하시면 됩니다
  • 43.