모던 c++ 문법

문자열 리터럴

Raw 문자열 리터럴

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

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

유니코드 문자열 리터럴

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

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

추가된 초기화 방식

지원: c++11
링크

lambda 표현식

지원: c++11
링크

constexpr 키워드

지원: c++11
링크

range based for

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

// 벡터 각각의 요소를 꺼내옴
for (const auto& num : my_vector) {
    std::cout << num << std::endl;
}

// 일반 배열에서도 사용 가능
for (const auto& num : my_array) {
    std::cout << num << std::endl;
}

구조분해 할당

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

std::pair<int, std::string> my_pair = {1, "Hello"};
auto [x, y] = my_pair;

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

nullptr

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

// stddef.h
#ifdef __cplusplus
    typedef decltype(nullptr) nullptr_t;      // nullptr의 타입을 nullptr_t로 지정
#endif
void foo(int num) {
    std::cout << "foo(int)" << '\n';
}

void foo(int *ptr) {
    std::cout << "foo(int*)" << '\n';
}

foo(0);         // foo(int) 출력
foo(NULL);      // foo(int) 출력
foo((int*)0);   // foo(int*) 출력
foo(nullptr);   // foo(int*) 출력

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

decltype

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

struct A {
  double d;
};

int& a;
decltype(a) b = 2;        // int&

A* aa;
decltype(aa->d) dd = 0.1; // double

auto foo = [](int a) -> decltype(a + 1) {   // decltype(a+1) == int
    return a * 2;
};

auto

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

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

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

const int x = 10;
auto y = x;       // int
int& a = 20;
auto b = a;       // int
auto& c = a;      // int&

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

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

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

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

typedef 대신 using

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

  1. typedef를 대체하여 사용. 좀 더 직관적이다.
typedef int id;
using id2 = int;

typedef void (*MyFunc)();
using MyFunc2 = void(*)();
  1. 템플릿 별칭도 지원한다.
template<typename T>
using List = std::list<T>;    // (o) 템플릿과 함께 사용가능
List<int> li;                

template<typename T>
typedef std::list<T> List;    // (x) Error. 템플릿과 같이 쓸수없다.

template<typename T>          // (o) c++11 이전까지는 이렇게썼다
struct List
{
    typedef std::list<T> type;
};
List<int>::type li2;

스마트포인터

지원: c++11
링크

Comments

ESC
Type to search...