모던 c++ 문법
문자열 리터럴 #
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 대신 사용할 수 있게 됐다.
- typedef를 대체하여 사용. 좀 더 직관적이다.
1typedef int id;
2using id2 = int;
3
4typedef void (*MyFunc)();
5using MyFunc2 = void(*)();
- 템플릿 별칭도 지원한다.
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
링크