모던 c++ 문법

모던 c++ 문법

2023년 6월 16일
c++11, c++14, c++17

문자열 리터럴 #

Raw 문자열 리터럴 #

지원: c++11
기존 문자열은 “…” 로 감싸고 내부의 특수문자를 이스케이핑 처리해줘야 하지만, R"(…)" 문자열은 이스케이핑 처리해줄 필요가 없는건 아니고 문자열을 닫는 )" 를 표시하기 위해서는 이스케이핑 처리해줘야 한다.
정규식 패턴을 표현할 때 유용하다.

1cout << R"(!@#$%^&*(\'"<>?:;)";
2cout << LR"(!@#$%^&*(\'"<>?:;)";    // wchar_t를 의미하는 L 과 혼용 가능

유니코드 문자열 리터럴 #

지원: c++11
다국어 지원이나 특수문자 처리할때 유용하다.

1auto s0 =   "hello"; // const char*
2auto s1 = u8"hello"; // const char* before C++20, encoded as UTF-8,
3                     // const char8_t* in C++20
4auto s2 =  L"hello"; // const wchar_t*
5auto s3 =  u"hello"; // const char16_t*, encoded as UTF-16
6auto s4 =  U"hello"; // const char32_t*, encoded as UTF-32

추가된 초기화 방식 #

지원: c++11
링크


lambda 표현식 #

지원: c++11
링크


constexpr 키워드 #

지원: c++11
링크


range based for #

지원: c++11
컨테이너의 요소를 쉽게 순회할 수 있는 방법이다.

1// 벡터 각각의 요소를 꺼내옴
2for (const auto& num : my_vector) {
3    std::cout << num << std::endl;
4}
5
6// 일반 배열에서도 사용 가능
7for (const auto& num : my_array) {
8    std::cout << num << std::endl;
9}

구조분해 할당 #

지원: c++17
복합 데이터 구조를 구조분해하여 개별요소에 대한 참조를 생성한다.

1std::pair<int, std::string> my_pair = {1, "Hello"};
2auto [x, y] = my_pair;
3
4std::vector<std::pair<int, std::string>> my_vec = {{1, "one"}, {2, "two"}, {3, "three"}};
5for (const auto& [num, str] : my_vec) {
6    std::cout << num << ": " << str << std::endl;
7}

nullptr #

지원: c++11 NULL 포인터 리터럴 상수이며 포인터를 초기화하는데 사용된다.
c++에서는 NULL 매크로가 정수 0으로 정의되어 있기 때문에 NULL을 사용하면 type safe하게 포인터를 표현할 수 없었다.

1// stddef.h
2#ifdef __cplusplus
3    typedef decltype(nullptr) nullptr_t;      // nullptr의 타입을 nullptr_t로 지정
4#endif
 1void foo(int num) {
 2    std::cout << "foo(int)" << '\n';
 3}
 4
 5void foo(int *ptr) {
 6    std::cout << "foo(int*)" << '\n';
 7}
 8
 9foo(0);         // foo(int) 출력
10foo(NULL);      // foo(int) 출력
11foo((int*)0);   // foo(int*) 출력
12foo(nullptr);   // foo(int*) 출력

nullptr로 원하는 타입의 함수를 호출할 수 있게된다.


decltype #

지원: c++11 컴파일타임에 표현식의 타입을 추론해서 반환한다.

 1struct A {
 2  double d;
 3};
 4
 5int& a;
 6decltype(a) b = 2;        // int&
 7
 8A* aa;
 9decltype(aa->d) dd = 0.1; // double
10
11auto foo = [](int a) -> decltype(a + 1) {   // decltype(a+1) == int
12    return a * 2;
13};

auto #

지원: c++11
c++11 이전에는 변수의 저장소 지속성을 지정하는데 사용했지만, 지금은 c++11 이전 버전에서도 사용되지 않고있다.
c++11 부터는 변수의 타입을 추론하는 키워드로 사용된다.
미리 공간을 할당해야하는 구조체나 클래스의 멤버로는 사용할 수 없다.

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

상수성과 참조는 누락되기 때문에 직접 지정해야한다.

1const int x = 10;
2auto y = x;       // int
3int& a = 20;
4auto b = a;       // int
5auto& c = a;      // int&

지원: c++14
함수의 반환타입도 자동으로 추론할 수 있도록 확장되었다.

1auto func(int a, string b) {
2    return a + b.size();
3}

지원: c++17
매개변수로도 지정할 수 있게됐다. 하지만 이것은 template을 간결하게 작성하기 위한 문법이기 때문에 템플릿처럼 각자 다른함수가 호출된다.

1auto func(auto a, auto b) {
2	  return a + b.size();
3}
4cout << func(3, string("test")) << endl;      // 7
5cout << func(1, vector<int>{1,2,3}) << endl;  // 4

typedef 대신 using #

지원: c++11
기존 c++에서는 using을 namespace를 지정할때 사용했지만, c++11부터 typedef 대신 사용할 수 있게 됐다.

  1. typedef를 대체하여 사용. 좀 더 직관적이다.
1typedef int id;
2using id2 = int;
3
4typedef void (*MyFunc)();
5using MyFunc2 = void(*)();
  1. 템플릿 별칭도 지원한다.
 1template<typename T>
 2using List = std::list<T>;    // (o) 템플릿과 함께 사용가능
 3List<int> li;                
 4
 5template<typename T>
 6typedef std::list<T> List;    // (x) Error. 템플릿과 같이 쓸수없다.
 7
 8template<typename T>          // (o) c++11 이전까지는 이렇게썼다
 9struct List
10{
11    typedef std::list<T> type;
12};
13List<int>::type li2;

스마트포인터 #

지원: c++11
링크

comments powered by Disqus