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>])]]
Visual Studio 2022 버전 17.14에서 도입된 이 Microsoft 특정 특성은 GSL(Guidelines Support Library) 규칙을 적용하는 검사기의 경고를 표시하지 않습니다. 문, 블록 또는 선언에 특성을 적용할 수 있습니다. C++에서만 사용할 수 있습니다. C 코드의 경우 대신 사용합니다 #pragma warning(suppress) .
<tag> 표시하지 않을 규칙의 이름을 지정하는 문자열입니다. 선택적 justification 필드를 사용하면 경고가 비활성화되거나 표시되지 않는 이유를 설명할 수 있습니다. 이 값은 옵션을 지정하면 SARIF(정적 분석 결과 교환 형식) 출력에 /analyze:log:includesuppressed 표시됩니다. 해당 값은 UTF-8로 인코딩된 좁은 문자열 리터럴입니다. SARIF 파일을 생성하려면 컴파일러 옵션을 사용합니다 /analyze:log:format:sarif .
예제:
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 특성을 사용하면 원치 않을 때 경고를 쉽게 끌 수 있습니다.
다음 중에서 #pragma warning 선택 [[gsl::suppress]]
[[gsl::suppress]] 경고 #pragma warning(suppress) 억제를 세밀하게 제어할 수 있습니다.
-
[[gsl::suppress]]Microsoft C++ Code Analysis 내보낸 경고만 표시하지 않습니다. 범위 또는 특정 선언에 적용할 수 있는 C++ 핵심 지침 검사와 함께 사용합니다. -
#pragma warning(suppress)는 컴파일러 경고에 사용할 수 있습니다. 코드의 구조를 크게 변경하지 않고 특정 코드 블록에서 경고를 표시하지 않는 경우에 유용합니다.
가능하면 [[gsl::suppress]] 사용하여 Microsoft C++ Code Analysis 경고를 표시하지 않습니다.
[[msvc::disable(feature:APX)]]
MSVC 빌드 도구 버전 14.51(Visual Studio 버전 18.6.0)에 도입된 [[msvc::disable(feature:APX)]] 특성은 특정 함수에 대한 Intel APX(Advanced Performance Extensions) 명령 생성을 사용하지 않도록 설정하는 x64 전용 Microsoft 특정 특성입니다. 함수 선언 또는 정의에 적용하면 컴파일러 옵션을 통해 /feature:APX APX가 전역적으로 사용하도록 설정된 경우에도 컴파일러가 해당 함수 본문에 APX 명령을 내보내지 못하게 합니다. 동일한 변환 단위의 다른 함수는 유사하게 특성이 지정되지 않는 한 APX 명령을 계속 사용합니다. 인라인 함수를 호출하는 함수 [[msvc::disable(feature:APX)]] 인 경우 인라인 코드도 APX 명령 없이 컴파일됩니다.
예시
// The following shows how to disable APX instructions for specific functions,
// even when APX is enabled globally with /feature:APX
int test(int argc)
{
auto lambda =
[]
[[msvc::disable(feature:APX)]]
(int argc)
{
return argc + 42;
};
return lambda(argc);
}
[[msvc::disable(feature:APX)]]
int test2(int x)
{
return x + 42;
}
[[msvc::enable(feature:APX)]]
/arch:APX 않고 APX 기능에 대한 함수별 옵트인을 제공합니다. 함수 [[msvc::enable(feature:APX)]] 에 인라인된 호출이 있는 경우 인라인 코드도 APX 명령으로 컴파일됩니다.
[[msvc::enable(feature:APX)]] 예제
// The following shows how to enable APX instructions for specific functions,
// even when APX isn't enabled globally with /feature:APX
int test(int argc)
{
auto lambda =
[]
[[msvc::enable(feature:APX)]]
(int argc)
{
return argc + 42;
};
return lambda(argc);
}
[[msvc::enable(feature:APX), msvc::noinline]]
int test2(int x)
{
return x + 42;
}
[[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::musttail]]
[[msvc::musttail]]에 도입된 이 특성은 비상 호출 최적화를 적용하는 실험적 x64 전용 Microsoft 전용 특성입니다. 정규화 반환 문에 적용하면 컴파일러가 호출을 비상 호출로 내보내도록 지시합니다. 컴파일러가 비상 호출을 내보낼 수 없으면 컴파일 오류가 발생합니다. 이 특성은 [[msvc::musttail]] 함수를 인라인하는 대신 비상 호출을 적용합니다.
[[msvc::musttail]] 요구 사항:
- 호출자와 호출 수신자는 일치하는 반환 형식이 있어야 합니다.
- 호출 규칙은 호환되어야 합니다.
- 비상 호출은 호출 함수의 최종 작업이어야 합니다.
- 호출 수신자는 호출 함수보다 더 많은 스택 공간을 사용할 수 없습니다.
- 4개 이상의 정수 매개 변수가 전달되는 경우 호출 함수는 다른 인수에 충분한 스택 공간을 할당해야 합니다.
-
/O2/O2 /GL또는 최적화 수준으로 컴파일합니다.
예시
비상 호출은 함수 호출이 반환하기 전에 수행된 마지막 작업일 때 가능한 컴파일러 최적화입니다. 함수를 호출하는 새 스택 프레임을 만드는 대신 현재 함수의 스택 프레임이 재사용됩니다. 이렇게 하면 스택 사용량이 줄어들고 특히 재귀 시나리오에서 성능이 향상됩니다.
다음 코드에서 적용된 [[msvc::musttail]] 특성으로 return increment(x) 인해 컨트롤이 직접 으로 전송됩니다 increment. 문에 도달하면 increment 해당 결과가 호출자에게 return x+1;직접 제공됩니다. 즉incrementIfPositive,main 이렇게 하면 인라인 increment 으로 또는 호출 incrementIfPositiveincrement 한 후 incrementIfPositive 로 돌아가기 전에 다시 찾게 됩니다incrementIfPositivemain. 비상 호출 최적화는 완료 후 incrementIfPositive 제어를 다시 얻을 필요가 increment 없습니다. 이는 스택 사용량을 줄이는 성능 최적화이며, 특히 재귀 시나리오에서 유용합니다.
// compile with /O2
#include <iostream>
int increment(int x)
{
return x + 1;
}
int incrementIfPositive(int x)
{
if (x > 0)
{
[[msvc::musttail]]
return increment(x);
}
return -1;
}
int main()
{
int result = incrementIfPositive(42);
if (result < 0)
{
return -1;
}
std::cout << result; // outputs 43
return 0;
}
[[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- 컴파일러 옵션을 사용합니다.