C++17 새로운 특성 개인 총화
컴 파 일 러 버 전:GCC 7.1,Clang 5.0
__cplusplus:201703L
컴 파일 옵션:-std=c+17
키워드
1.1 constexpr
constexpr 사용 범 위 를 확장 합 니 다.if 구문 에 도 사용 할 수 있 고 lambda 표현 식 에 도 사용 할 수 있 습 니 다.
예 1:
#include<iostream>
template<bool ok>
constexpr void foo()
{
// ,if else
if constexpr (ok == true)
{
// ok true , else
std::cout << "ok" << std::endl;
}
else
{
// ok false , if
std::cout << "not ok" << std::endl;
}
}
int main()
{
foo<true>();// ok, std::cout << "ok" << std::endl;
foo<false>();// not ok, std::cout << "not ok" << std::endl;
return 0;
}
예 2:
int main()
{
constexpr auto add1 = [](int n, int m){
auto func1 = [=] { return n; }; //func1 lambda
auto func2 = [=] { return m; }; //func2 lambda
return [=] { return func1() + func2(); };
};
constexpr auto add2 = [](int n, int m){
return n + m;
};
auto add3 = [](int n, int m){
return n + m;
};
int sum1 = add1(30, 40)( ); // ,add1 , 70
int sum2 = add2(sum1, 4); // constexpr ,add2 constexpr , lambda
constexpr int sum3 = add3(1, 2); //sum3 constexpr , ,add3 lambda, 3
int sum4 = add2(10, 2);// ,add2 , 12
return 0;
}
1.2 static_assert확장 staticassert 용법,정적 단언 의 디 스 플레이 텍스트 를 선택 할 수 있 습 니 다.
예:
static_assert(true, "");
static_assert(true);//c++17
1.3 autoauto 추정 범위 확장
예:
auto x1 = { 1, 2 }; // std::initializer_list<int>
auto x2 = { 1, 2.0 }; // : ,
auto x3{ 1, 2 }; // :auto
auto x4 = { 3 }; // std::initializer_list<int>
auto x5{ 3 }; // int
1.4 typename확장 용법 은 템 플 릿 의 템 플 릿 인자 에 나타 날 수 있 습 니 다.
먼저 type:name 의 용법 을 돌 이 켜 보면 ① 템 플 릿 에 사용 되 며 템 플 릿 매개 변 수 를 유형 으로 표시 합 니 다.② 어떤 이름 이 변수 이름 임 을 설명 하 는 데 사 용 됩 니 다.
예 1:
struct A
{
typedef int Example;
};
// :
template<typename T>
struct B { };
struct C
{
typedef typename A::Example E;// :
};
int main()
{
typename A::Example e;// :
return 0;
}
새로운 기능 의 type:name 용법,예 2:
#include<iostream>
#include<typeinfo>
template<typename T>
struct A
{
int num;
A()
{
std::cout << "A Construct" << std::endl;
std::cout << "template typename is: " << typeid (T).name() << std::endl;
}
};
// T ,X ,T X typename class
template<template<typename T> typename X>
struct B
{
X<double> e;
B() { std::cout << "B Construct" << std::endl; }
};
int main()
{
A<B<A>> a;
std::cout << "***************************" << std::endl;
B<A> b;
return 0;
}
실행 결과:1.5 inline
확장 용법 은 내 연 변 수 를 정의 하 는 데 사용 되 며,기능 은 내 연 함수 와 비슷 합 니 다.inline 은 함수 나 변수 가 다 중 으로 정의 되 는 문 제 를 피 할 수 있 습 니 다.같은 함수 나 변 수 를 정의 하고 이 함수 나 변 수 를 inline 으로 설명 하면 컴 파일 러 는 이 함수 나 변 수 를 자동 으로 연결 합 니 다.
(오류 가 발생 하지 않 음):
// test.h
inline void print()
{
std::cout << "hello world" << std::endl;
}
inline int num = 0;
// func.h
include "test.h"
inline void add(int arg)
{
num += arg;
print();
}
// main.cpp
include "func.h"
int main()
{
num = 0;
print();
add(10);
return 0;
}
문법2.1 접 이식
길 어 지 는 매개 변수 템 플 릿 의 패키지 해제 에 사용 되 며,각종 연산 자(연산 자 와)만 지원 하 며,왼쪽,오른쪽 으로 나 누 어 접 습 니 다.
예:
#include<string>
template<typename ... T>
auto sum(T ... arg)
{
return (arg + ...);//
}
template<typename ... T>
double sum_strong(T ... arg)
{
return (arg + ... + 0);//
}
template<typename ... T>
double sub1(T ... arg)
{
return (arg - ...);//
}
template<typename ... T>
double sub2(T ... arg)
{
return (... - arg);//
}
int main()
{
int s1 = sum(1, 2, 2, 4, 5);// :((((1+)2+)3+)4+)5 = 15
double s2 = sum(1.1, 2.2, 3.3, 4.4, 5.5, 6.6);
double s3 = sum(1, 2.2, 3, 4.4, 5);
double s4 = sub1(5, 2, 1, 1);// :((((5-)2-)1-)1) = 1
double s5 = sub2(5, 2, 1, 1);// :(5-(2-(1-(1)))) = 3
double s6 = sum_strong();//s6 = 0
std::string str1("he");
std::string str2("ll");
std::string str3("o ");
std::string str4("world");
std::string str5 = sum(str1, str2, str3, str4);//str5 = "hello world"
return 0;
}
2.2 구조 화 귀속하나 이상 의 변 수 를 포함 하 는 중 괄호 로 구조 화 바 인 딩 을 표시 하지만 구조 화 바 인 딩 을 사용 할 때 는 auto 키워드,즉 정시 성명 변 수 를 묶 어야 합 니 다.
예 1:
/*
* :
*/
struct S
{
double num1;
long num2;
};
S foo(int arg1, double arg2)
{
double result1 = arg1 * arg2;
long result2 = arg2 / arg1;
return {result1, result2};// S
};
int main()
{
auto [num1, num2] = foo(10, 20.2);// num1 double,num2 long
return 0;
}
예 2:
#include<list>
#include<map>
/*
* :
*/
template<typename T, typename U>
struct MyStruct
{
T key;
U value;
};
int main()
{
std::list<MyStruct<int, double>> Container1;
std::map<int, MyStruct<long long, char>> Container2;
for(auto [key, value] : Container1)
{
//key int ,value double
}
for(auto [key, value] : Container2)
{
//key int ,value MyStruct<long long, char>
//value1 long long ,value2 char
auto [value1, value2] = value;
}
return 0;
}
2.3 비 유형 템 플 릿 매개 변 수 를 상수 로 계산 할 수 있 습 니 다.비 형식 템 플 릿 매개 변 수 는 클래스 의 정적 구성원 에 게 전 달 될 수 있 습 니 다.
예:
class MyClass
{
public:
static int a;
};
template<int *arg>
void foo() {}
int main()
{
foo<&MyClass::a>();
return 0;
}
2.4 조건 부 분기 문 초기 화if 와 switch 에서 초기 화 가능
예:
template<long value>
void foo(int &ok)
{
if constexpr (ok = 10; value > 0)
{
}
}
int main()
{
int num = 0;
if(int i = 0; i == 0)
{
}
foo<10>(num);
switch(int k = 10; k)
{
case 0:break;
case 1:break;
default:break;
}
return 0;
}
2.5 중합 초기 화대상 을 초기 화 할 때 괄호 로 구성원 에 게 값 을 부여 할 수 있 습 니 다.
예:
struct MyStruct1
{
int a;
int b;
};
struct MyStruct2
{
int a;
MyStruct1 ms;
};
int main()
{
MyStruct1 a{10};
MyStruct2 b{10, 20};
MyStruct2 c{1, {}};
MyStruct2 d{{}, {}};
MyStruct2 e{{}, {1, 2}};
return 0;
}
2.6 내장 네 임 스페이스다 중 네 임 스페이스 의 작성 을 간소화 하 다.
예:
//
namespace A
{
namespace B
{
namespace C
{
};
};
};
//
namespace A::B::C
{
};
2.7 lambda 표현 식 캡 처*this 값lambda 표현 식 은*this 의 값 을 캡 처 할 수 있 지만 this 와 그 구성원 은 읽 기 전용 입 니 다.
예:
struct MyStruct {
double ohseven = 100.7;
auto f() {
return [this] {
return [*this] {
this->ohseven = 200.2;// ,
return ohseven;//
};
}();
}
auto g() {
return []{
return [*this]{};// , lambda this
}();
}
};
2.8 매 거 대상 의 구조매개[클래스]대상 에 게 값 을 부여 할 수 있 습 니 다.
예:
enum MyEnum { value };
MyEnum me {10};// : int MyEnum
enum byte : unsigned char { };
byte b { 42 }; //
byte c = { 42 }; // : int byte
byte d = byte{ 42 }; // , b
byte e { -1 }; // : -1 byte
struct A { byte b; };
A a1 = { { 42 } }; // : int byte
A a2 = { byte{ 42 } }; //
void f(byte);
f({ 42 }); // :
enum class Handle : unsigned int { value = 0 };
Handle h { 42 }; //
2.9 16 진 단일 정밀도 부동 소수점 숫자 액면가0x 접두사 로 시작 하 는 16 진수,f 접두사 의 단일 정밀도 부동 소수점,합병 하면 16 진수 의 단일 정밀도 부동 소수점 이 있 습 니 다.
예:
int main()
{
float value = 0x1111f;
return 0;
}
2.10 메모리 정렬 기반 동적 메모리 할당동적 메모리 할당 에 대해 서 는 new 와 delete 연산 자가 빠 질 수 없습니다.새로운 표준 의 new 와 delete 연산 자 는 메모리 값 을 맞 추고 메모리 공간 을 분배 하고 방출 하 는 기능 을 추 가 했 습 니 다.(즉,메모리 값 을 맞 추 는 new,delete 연산 자 를 다시 불 러 옵 니 다)
함수 원형:
void* operator new(std::size_t size, std::align_val_t alignment);
void* operator new[](std::size_t size, std::align_val_t alignment);
void operator delete(void*, std::size_t size, std::align_val_t alignment);
void operator delete[](void*, std::size_t size, std::align_val_t alignment);
매개 변수 설명:분 배 된 바이트 수.alignment 의 정수 배 여야 합 니 다.
alignment―지정 한 메모리 값 정렬.반드시 지 지 를 실현 하 는 합 법 적 인 정렬 이 어야 한다.
new 의 반환 값:
성공,새 할당 메모리 의 시작 주 소 를 가리 키 는 지침 을 되 돌려 줍 니 다.
용법 예:
#include<new>
struct alignas(8) A {};
int main()
{
A *a = static_cast<A *>(::operator new(sizeof(A), static_cast<std::align_val_t>(alignof (A))));
::operator delete(a, sizeof(A), static_cast<std::align_val_t>(alignof (A)));
return 0;
}
2.11 세분 화 식 의 계산 순서범용 프로 그래 밍 과 과부하 연산 자의 광범 위 한 사용 을 지원 하기 위해 새로운 기능 은 계산 순 서 를 세분 화 합 니 다.
다음 논란 코드 세그먼트:
#include<map>
int main()
{
std::map<int, int> tmp;
// std::map [] , [] key ,std::map
tmp[0] = tmp.size();// {0, 0} {0, 1}
return 0;
}
이 상황 을 해결 하기 위해 새로운 계산 순서 규칙 은 다음 과 같다.① 접미사 표현 식 은 왼쪽 에서 오른쪽으로 값 을 구한다.이것 은 함수 호출 과 구성원 선택 표현 식 을 포함 합 니 다.
② 할당 식 은 오른쪽 에서 왼쪽으로 값 을 구 합 니 다.이것 은 복합 할당 을 포함한다.
③ 왼쪽 에서 오른쪽으로 이동 연산 자의 조작 수 를 계산한다.
2.1.2 템 플 릿 류 의 템 플 릿 매개 변수 자동 유도
템 플 릿 클래스 의 대상 을 정의 할 때 템 플 릿 파 라 메 터 를 지정 하지 않 아 도 되 지만 구조 함수 에서 템 플 릿 파 라 메 터 를 유도 해 야 합 니 다.
예:
template<class T> struct A {
explicit A(const T&, ...) noexcept {} // #1
A(T&&, ...){} // #2
};
int i;
A a1 = { i, i }; //오류,\#1 에 따라 오른쪽 값 으로 유도 할 수 없고\#1 을 통 해 복사 초기 화 할 수 없습니다.A a2{i, i}; //정확,호출\#1 초기 화 에 성 공 했 습 니 다.a2 는 A
A a3{0, i}; //정확 합 니 다.호출\#2 초기 화 에 성 공 했 습 니 다.a2 는 A
A a4 = {0, i}; //정확 합 니 다.호출\#2 초기 화 에 성 공 했 습 니 다.a2 는 A
template<class T> A(const T&, const T&) -> A<T&>; // #3
template<class T> explicit A(T&&, T&&) -> A<T>; // #4
A a5 = {0, 1}; //오류,\#1 과\#2 구조 함수 결과 가 같 습 니 다(즉 충돌).\#3 에 따라 AA a6{0, 1}; //정확 합 니 다.\#2 를 통 해 A
A a7 = {0, i}; //오류,비 정적 왼쪽 값 을 오른쪽 값 으로 연결 할 수 없습니다.\#3 에 따라 A
A a8{0, i}; //오류,비 정적 왼쪽 값 을 오른쪽 값 으로 연결 할 수 없습니다.\#3 에 따라 A
template<class T>
struct B {
template<class U>
using TA = T;//
template<class U>
B(U, TA<U>);//
};
B b{(int*)0, (char*)0}; //정확,B2.13 중복 네 임 스페이스 의 속성 목록 간소화
예:
[[ using CC: opt(1), debug ]] void f() {}
// [[ CC::opt(1), CC::debug ]] void f() {}
2.14 지원 되 지 않 고 표준 이 아 닌 속성속성 목록 을 추가 할 때 컴 파 일 러 는 지원 하지 않 는 비표 준 속성 을 무시 하고 경고 와 오 류 를 보 내지 않 습 니 다.
2.15 개작 과 계승 구조 함수
클래스 의 계승 체계 에서 구조 함수 의 자동 호출 은 골 치 아 픈 문제 이다.새로운 특성 은 계승 과 구조 함수 의 용법 을 도입 한다.
예 1:
#include<iostream>
struct B1
{
B1(int) { std::cout << "B1" << std::endl; }
};
struct D1 : B1 {
using B1::B1;// B1
};
D1 d1(0); // , , B1::B1(int)
예 2:
#include<iostream>
struct B1
{
B1(int) { std::cout << "B1" << std::endl; }
};
struct B2
{
B2(int) { std::cout << "B2" << std::endl; }
};
struct D1 : B1, B2 {
using B1::B1;// B1
using B2::B2;// B2
};
D1 d1(0); // : ,
struct D2 : B1, B2
{
using B1::B1;
using B2::B2;
// ,D2::D2(int) B1::B1(int) B2::B2(int)。 B1 B2 , B1 B2
D2(int) : B1(1), B2(0)
{ std::cout << "D2" << std::endl; }
};
struct D3 : B1
{
using B1::B1;
};
D3 d3(0);// , B1 , B1 , B1
//
int main()
{
D2 d(100);// , B1 B2 D2
return 0;
}
예 3:
#include<iostream>
struct B1
{
B1() { std::cout << "B1 default" << std::endl; }
B1(int) { std::cout << "B1" << std::endl; }
};
struct B2
{
B2() { std::cout << "B2 default" << std::endl; }
B2(int) { std::cout << "B2" << std::endl; }
};
struct D1 : B1, B2
{
using B1::B1;
using B2::B2;
// ,D2::D2(int) B1::B1(int) B2::B2(int), B1 B2
D1(int) : B1(1), B2(0)
{ std::cout << "D2" << std::endl; }
// ,
D1() { std::cout << "D2 default" << std::endl; }
};
//
int main()
{
D1 d(100);// , B1 B2 D2
D1 dd;
//
//B1 default
//B2 default
//D2 default
return 0;
}
2.16 내 연 변수보이다
2.17 auto 를 비 유형 템 플 릿 매개 변수 로 사용 합 니 다.
템 플 릿 매개 변수 가 비 형식 일 때 auto 자동 유도 형식 을 사용 할 수 있 습 니 다.
예:
#include<iostream>
template<auto T>
void foo()
{
std::cout << T << std::endl;
}
int main()
{
foo<100>();// 100
foo<int>();//no matching function for call to "foo<int>()"
return 0;
}
3 매크로3.1 __has_include
어떤 파일 이 포함 되 어 있 는 지 판단 합 니 다.
예:
int main()
{
#if __has_include(<cstdio>)
printf("hehe");
#endif
#if __has_include("iostream")
std::cout << "hehe" << std::endl;
#endif
return 0;
}
4 속성4.1 fallthrough
switch 구문 블록 에 사용 하면 다음 케이스 나 default 를 실행 할 것 임 을 표시 합 니 다.
예:
int main()
{
int ok1, ok2;
switch (0)
{
case 0:
ok1 = 0;
[[fallthrough]];
case 1:
ok2 = 1;
[[fallthrough]];
}
return 0;
}
4.2 nodiscard클래스 성명,함수 성명,매 거 진 성명 에 사용 할 수 있 으 며 함수 의 반환 값 이 수신 되 지 않 았 음 을 나타 내 며 컴 파일 할 때 경고 가 나타 납 니 다.
예:
[[nodiscard]] class A {}; //
[[nodiscard]] enum class B {}; //
class C {};
[[nodiscard]] int foo()
{ return 10; }
[[nodiscard]] A func1() { return A(); }
[[nodiscard]] B func2() { return B(); }
[[nodiscard]] C func3() { return C(); }
int main()
{
foo();//warning: ignoring return value
func1();//warning: ignoring return value
func2();//warning: ignoring return value
func3();//warning: ignoring return value
return 0;
}
4.3 maybe_unused클래스,type:def,변수,비정 상 데이터 구성원,함수,매 거 진 또는 매 거 진 값 에 사용 할 수 있 습 니 다.컴 파일 러 가 사용 하지 않 은 실체 에 대한 경 고 를 억제 하 는 데 사용 된다.즉,이 속성 을 더 하면 어떤 실체 에 대해'쓸모 없다'는 경 고 를 하지 않 는 다.
용법 예:
[[maybe_unused]] class A {};
[[maybe_unused]] enum B {};
[[maybe_unused]] int C;
[[maybe_unused]] void fun();
결어이번 검사 에 서 는 C++17 의 새로운 특성 에 GCC 컴 파 일 러 를 사 용 했 으 며,Clang 의 지원 성에 대해 서 는 차이 점 을 측정 하지 않 았 다.문제 가 있 으 면 지적 해 주 십시오.
C++17 의 새로운 특성 에 대한 개인 적 인 정리 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C++17 의 새로운 특성 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 도 많은 응원 부탁드립니다!