C++의 특성

C++ 표준은 공통 특성 집합을 정의합니다. 또한 컴파일러 공급업체는 공급업체별 네임스페이스 내에서 고유한 특성을 정의할 수 있습니다. 그러나 컴파일러는 표준에 정의된 특성을 인식하기만 해야 합니다.

경우에 따라 표준 특성은 컴파일러별 __declspec 매개 변수와 겹칩니다. Microsoft C++에서는 을 [[deprecated]] 사용하는 __declspec(deprecated)대신 특성을 사용할 수 있습니다. 특성은 [[deprecated]] 모든 준수 컴파일러에서 인식됩니다. 등과 dllexport같은 dllimport 다른 __declspec 모든 매개 변수의 경우 지금까지는 해당하는 특성이 없으므로 구문을 계속 사용해야 __declspec 합니다. 특성은 형식 시스템에 영향을 주지 않으며 프로그램의 의미를 변경하지 않습니다. 컴파일러는 인식할 수 없는 특성 값을 무시합니다.

Visual Studio 2017 버전 15.3 이상 (사용 가능 /std:c++17 및 이후 버전): 특성 목록의 범위에서 단일 using 소개자를 사용하여 모든 이름의 네임스페이스를 지정할 수 있습니다.

void g() {
    [[using rpr: kernel, target(cpu,gpu)]] // equivalent to [[ rpr::kernel, rpr::target(cpu,gpu) ]]
    do task();
}

C++ 표준 특성

C++11에서 특성은 C++ 구문(클래스, 함수, 변수 및 블록 포함)에 추가 정보를 주석으로 추가하는 표준화된 방법을 제공합니다. 특성은 공급업체별 특성일 수도 있으며 그렇지 않을 수도 있습니다. 컴파일러는 이 정보를 사용하여 정보 메시지를 생성하거나 특성 코드를 컴파일할 때 특수 논리를 적용할 수 있습니다. 컴파일러는 인식할 수 없는 특성을 무시합니다. 즉, 이 구문을 사용하여 사용자 고유의 사용자 지정 특성을 정의할 수 없습니다. 특성은 이중 대괄호로 묶입니다.

[[deprecated]]
void Foo(int);

특성은 지시문( __declspec() Visual C++) 또는 __attribute__ GNU()와 같은 #pragma 공급업체별 확장에 대한 표준화된 대안을 나타냅니다. 그러나 대부분의 용도로 공급업체별 구문을 사용해야 합니다. 표준은 현재 준수 컴파일러가 인식해야 하는 다음 특성을 지정합니다.

[[carries_dependency]]

이 특성은 [[carries_dependency]] 함수가 스레드 동기화에 대한 데이터 종속성 순서를 전파하도록 지정합니다. 전달된 인수가 함수 본문에 종속성을 전달하도록 지정하기 위해 하나 이상의 매개 변수에 특성을 적용할 수 있습니다. 반환 값이 함수에서 종속성을 전달하도록 지정하기 위해 함수 자체에 특성을 적용할 수 있습니다. 컴파일러는 이 정보를 사용하여 보다 효율적인 코드를 생성할 수 있습니다.

[[deprecated]]

Visual Studio 2015 이상: 이 특성은 [[deprecated]] 함수가 사용되지 않도록 지정합니다. 또는 이후 버전의 라이브러리 인터페이스에 존재하지 않을 수 있습니다. 특성은 [[deprecated]] 클래스, typedef-name, 변수, 비정적 데이터 멤버, 함수, 네임스페이스, 열거형, 열거자 또는 템플릿 특수화의 선언에 적용할 수 있습니다. 컴파일러는 클라이언트 코드가 함수를 호출하려고 할 때 이 특성을 사용하여 정보 메시지를 생성할 수 있습니다. Microsoft C++ 컴파일러가 항목 사용을 [[deprecated]] 감지하면 컴파일러 경고 C4996이 발생합니다.

[[fallthrough]]

Visual Studio 2017 이상: (사용 가능 및 /std:c++17 이후 버전) 이 특성은 [[fallthrough]] 문 컨텍스트에서 대체 동작이 switch 의도된 컴파일러(또는 코드를 읽는 모든 사용자)에 대한 힌트로 사용할 수 있습니다. Microsoft C++ 컴파일러는 현재 대체 동작에 대해 경고하지 않으므로 이 특성은 컴파일러 동작에 영향을 주지 않습니다.

[[likely]]

Visual Studio 2019 버전 16.6 이상: (사용 가능 및 /std:c++20 이후 버전) 특성은 [[likely]] 특성 레이블 또는 문의 코드 경로가 대안보다 실행될 가능성이 더 높다는 힌트를 컴파일러에 지정합니다. Microsoft 컴파일러 [[likely]] 에서 특성은 블록을 내부 최적화 점수를 증가시키는 "핫 코드"로 표시합니다. 속도에 최적화할 때 점수가 더 증가하며 크기를 최적화할 때는 그다지 증가하지 않습니다. 순 점수는 인라인 처리, 루프 언롤링 및 최적화 벡터화 가능성에 영향을 줍니다. 프로필 기반 최적화[[likely]] 효과와 [[unlikely]] 유사하지만 범위는 현재 번역 단위로 제한됩니다. 블록 다시 정렬 최적화는 이 특성에 대해 아직 구현되지 않았습니다.

[[maybe_unused]]

Visual Studio 2017 버전 15.3 이상: (사용 가능 및 /std:c++17 이후 버전) 이 특성은 [[maybe_unused]] 변수, 함수, 클래스, typedef, 비정적 데이터 멤버, 열거형 또는 템플릿 특수화가 의도적으로 사용되지 않을 수 있음을 지정합니다. 표시된 [[maybe_unused]] 엔터티가 사용되지 않는 경우 컴파일러는 경고하지 않습니다. 특성 없이 선언된 엔터티는 나중에 특성으로 다시 선언될 수 있으며 그 반대의 경우도 마찬가지입니다. 엔터티는 표시된 첫 번째 선언 이후와 현재 번역 단위의 나머지 부분에 대해 표시된 [[maybe_unused]] 것으로 간주됩니다.

[[nodiscard]]

Visual Studio 2017 버전 15.3 이상: (사용 가능 및 /std:c++17 이후 버전) 함수의 반환 값이 디스카드되지 않도록 지정합니다. 다음 예제와 같이 경고 C4834를 발생합니다.

[[nodiscard]]
int foo(int i) { return i * i; }

int main()
{
    foo(42); //warning C4834: discarding return value of function with 'nodiscard' attribute
    return 0;
}

[[noreturn]]

이 특성은 [[noreturn]] 함수가 반환되지 않도록 지정합니다. 즉, 항상 예외를 throw하거나 종료합니다. 컴파일러는 엔터티에 대한 [[noreturn]] 컴파일 규칙을 조정할 수 있습니다.

[[unlikely]]

Visual Studio 2019 버전 16.6 이상: (사용 가능 및 /std:c++20 이후 버전) 특성은 [[unlikely]] 특성 레이블 또는 문의 코드 경로가 대안보다 실행 가능성이 적다는 힌트를 컴파일러에 지정합니다. Microsoft 컴파일러 [[unlikely]] 에서 특성은 블록을 내부 최적화 점수를 감소시키는 "콜드 코드"로 표시합니다. 크기에 최적화할 때 점수가 더 감소하며 속도 최적화 시에는 그다지 감소하지 않습니다. 순 점수는 인라인 처리, 루프 언롤링 및 최적화 벡터화 가능성에 영향을 줍니다. 블록 다시 정렬 최적화는 이 특성에 대해 아직 구현되지 않았습니다.

Microsoft 관련 특성

[[gsl::suppress(rules)]]

Microsoft 관련 [[gsl::suppress(rules)]] 특성은 코드에서 GSL(Guidelines Support Library) 규칙을 적용하는 검사ers의 경고를 표시하지 않는 데 사용됩니다. 예를 들어 다음 코드 조각을 고려합니다.

int main()
{
    int arr[10]; // GSL warning C26494 will be fired
    int* p = arr; // GSL warning C26485 will be fired
    [[gsl::suppress(bounds.1)]] // This attribute suppresses Bounds rule #1
    {
        int* q = p + 1; // GSL warning C26481 suppressed
        p = q--; // GSL warning C26481 suppressed
    }
}

이 예제에서는 다음과 같은 경고를 발생합니다.

  • C26494 (형식 규칙 5: 항상 개체를 초기화합니다.)

  • C26485 (경계 규칙 3: 포인터 감쇠에 대한 배열 없음)

  • C26481 (경계 규칙 1: 포인터 산술 연산을 사용하지 마세요. 대신 범위를 사용합니다.)

처음 두 경고는 CppCoreCheck 코드 분석 도구를 설치하고 활성화하여 이 코드를 컴파일할 때 발생합니다. 그러나 세 번째 경고는 특성 때문에 발생하지 않습니다. 특정 규칙 번호를 포함하지 않고 작성 [[gsl::suppress(bounds)]] 하여 전체 경계 프로필을 표시하지 않을 수 있습니다. C++ 핵심 지침은 더 안전하고 안전한 코드를 작성하는 데 도움이 되도록 설계되었습니다. suppress 특성을 사용하면 원하지 않을 때 경고를 쉽게 끌 수 있습니다.

[[msvc::flatten]]

Microsoft 관련 특성 [[msvc::flatten]] 은 매우 유사 [[msvc::forceinline_calls]]하며 동일한 위치와 동일한 방식으로 사용할 수 있습니다. 차이점은 호출이 [[msvc::flatten]][[msvc::forceinline_calls]] 남아 있지 않을 때까지 재귀적으로 적용되는 범위의 모든 호출입니다. 이로 인해 함수의 결과 코드 크기 증가 또는 수동으로 관리해야 하는 컴파일러의 처리량에 영향을 미칠 수 있습니다.

[[msvc::forceinline]]

함수 선언 앞에 배치되는 경우 Microsoft 관련 특성 [[msvc::forceinline]] 은 .와 __forceinline같은 의미를 가짐

[[msvc::forceinline_calls]]

Microsoft 관련 특성 [[msvc::forceinline_calls]] 은 문 또는 블록 위 또는 그 앞에 배치할 수 있습니다. 인라인 추론이 해당 문의 모든 호출을 시도하거나 차단합니다 [[msvc::forceinline]] .

void f() {
    [[msvc::forceinline_calls]]
    {
        foo();
        bar();
    }
    ...
    [[msvc::forceinline_calls]]
    bar();
    
    foo();
}

첫 번째 호출과 두 호출 foobar모두 선언된 것처럼 처리됩니다__forceinline. 두 번째 호출 foo 은 로 처리 __forceinline되지 않습니다.

[[msvc::intrinsic]]

특성에는 [[msvc::intrinsic]] 적용되는 함수에 대한 세 가지 제약 조건이 있습니다.

  • 함수는 재귀적일 수 없습니다. 해당 본문에는 매개 변수 형식에서 반환 형식으로의 return 문 static_cast 만 있어야 합니다.
  • 함수는 단일 매개 변수만 수락할 수 있습니다.
  • /permissive- 컴파일러 옵션이 필요합니다. (이상 /std:c++20 옵션은 기본적으로 의미합니다 /permissive- .)

Microsoft 관련 [[msvc::intrinsic]] 특성은 매개 변수 형식에서 반환 형식으로 명명된 캐스트 역할을 하는 메타 함수를 인라인으로 컴파일러에 지시합니다. 함수 정의에 특성이 있으면 컴파일러는 해당 함수에 대한 모든 호출을 간단한 캐스트로 바꿉니다. 이 특성은 [[msvc::intrinsic]] Visual Studio 2022 버전 17.5 미리 보기 2 이상 버전에서 사용할 수 있습니다. 이 특성은 뒤에 오는 특정 함수에만 적용됩니다.

예시

이 샘플 코드 [[msvc::intrinsic]] 에서 함수에 my_move 적용된 특성은 컴파일러가 함수에 대한 호출을 본문의 인라인 정적 캐스트로 대체합니다.

template <typename T>
[[msvc::intrinsic]] T&& my_move(T&& t) { return static_cast<T&&>(t); }

void f() {
    int i = 0;
    i = my_move(i);
}

[[msvc::noinline]]

함수 선언 앞에 배치되는 경우 Microsoft 관련 특성 [[msvc::noinline]] 은 .와 declspec(noinline)같은 의미를 가짐

[[msvc::noinline_calls]]

Microsoft 관련 특성 [[msvc::noinline_calls]] 의 사용법은 .와 동일합니다 [[msvc::forceinline_calls]]. 문이나 블록 앞에 배치할 수 있습니다. 해당 블록의 모든 호출을 강제로 인라인하는 대신 적용된 범위에 대한 인라인을 해제하는 효과가 있습니다.

[[msvc::no_tls_guard]]

Microsoft 관련 [[msvc::no_tls_guard]] 특성은 DLL의 스레드-로컬 변수에 대한 첫 번째 액세스에서 초기화를 위해 검사 사용하지 않도록 설정합니다. 검사 Visual Studio 2019 버전 16.5 이상을 사용하여 빌드된 코드에서 기본적으로 사용하도록 설정됩니다. 이 특성은 뒤에 오는 특정 변수에만 적용됩니다. 전역적으로 검사 사용하지 않도록 설정하려면 컴파일러 옵션을 사용합니다/Zc:tlsGuards-.