C++ 표준은 공통 특성 집합을 정의합니다. 또한 컴파일러 공급업체가 공급업체별 네임스페이스 내에서 자체 특성을 정의할 수 있습니다. 그러나 컴파일러는 표준에 정의된 특성을 인식하기만 해야 합니다.
경우에 따라 표준 특성은 컴파일러별 __declspec
매개 변수와 겹칩니다. Microsoft C++에서는 [[deprecated]]
을(를) 사용하는 대신 __declspec(deprecated)
특성을 사용할 수 있습니다.
[[deprecated]]
특성은 모든 준수 컴파일러에서 인식됩니다.
__declspec
및 dllimport
등의 다른 모든 dllexport
매개변수의 경우 지금까지는 해당하는 특성이 없으므로 __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);
특성은 #pragma
지시문, __declspec()
(Visual C++) 또는 __attribute__
(GNU)와 같은 공급업체별 확장에 대한 표준화된 대안을 나타냅니다. 그러나 대부분의 목적에서는 여전히 공급업체별 구성을 사용해야 합니다. 현재 표준은 호환 컴파일러가 인식해야 하는 다음 특성을 지정하고 있습니다.
[[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++ 컴파일러는 현재 fallthrough 동작에 대해 경고하지 않으므로 이 특성은 컴파일러 동작에 영향을 주지 않습니다.
[[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(<tag> [, justification: <narrow-string-literal>])]]
<tag>
표시하지 않을 규칙의 이름을 지정하는 문자열입니다. 선택적 justification
필드를 사용하면 경고가 비활성화되거나 표시되지 않는 이유를 설명할 수 있습니다. 이 값은 옵션이 지정되면 SARIF 출력에 /analyze:log:includesuppressed
표시됩니다. 해당 값은 UTF-8로 인코딩된 좁은 문자열 리터럴입니다. 이 [[gsl::suppress]]
특성은 Visual Studio 2022 버전 17.14 이상 버전에서 사용할 수 있습니다.
Microsoft별 [[gsl::suppress]]
특성은 코드에서 GSL(Guidelines Support Library) 규칙을 적용하는 검사기의 경고를 표시하지 않는 데 사용됩니다. 예를 들어 다음 코드 조각을 고려하세요.
int main()
{
int arr[10]; // GSL warning C26494 will be fired
int* p = arr; // GSL warning C26485 will be fired
[[gsl::suppress("bounds.1", justification: "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();
}
foo
에 대한 첫 번째 호출과 bar
에 대한 두 번째 호출은 __forceinline
(으)로 선언된 것처럼 취급됩니다.
foo
에 대한 두 번째 호출은 __forceinline
(으)로 취급되지 않습니다.
[[msvc::intrinsic]]
[[msvc::intrinsic]]
특성에는 적용되는 함수에 대한 세 가지 제약 조건이 있습니다.
- 함수는 재귀적일 수 없으며, 본문에는 매개변수 유형에서 반환 유형까지
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-
컴파일러 옵션을 사용합니다.