Attribute in C++

Der C++-Standard definiert einen allgemeinen Satz von Attributen. Außerdem können Compilerhersteller ihre eigenen Attribute innerhalb eines anbieterspezifischen Namespaces definieren. Compiler sind jedoch nur erforderlich, um die im Standard definierten Attribute zu erkennen.

In einigen Fällen überlappen sich Standardattribute mit compilerspezifischen Parametern __declspec . In Microsoft C++ können Sie das [[deprecated]] Attribut anstelle der Verwendung verwenden __declspec(deprecated). Das [[deprecated]] Attribut wird von einem konformen Compiler erkannt. Für alle anderen __declspec Parameter wie dllimport und dllexport, bisher gibt es keine Attributentsprechung, daher müssen Sie die Syntax weiterhin verwenden __declspec . Attribute wirken sich nicht auf das Typsystem aus, und sie ändern nicht die Bedeutung eines Programms. Compiler ignorieren Attributwerte, die sie nicht erkennen.

Visual Studio 2017, Version 15.3 und höher (verfügbar mit /std:c++17 und höher): Im Bereich einer Attributliste können Sie den Namespace für alle Namen mit einer einzelnen using Einführung angeben:

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

C++-Standardattribute

In C++11 bieten Attribute eine standardisierte Möglichkeit zum Kommentieren von C++-Konstrukten (einschließlich, aber nicht beschränkt auf Klassen, Funktionen, Variablen und Blöcke) mit zusätzlichen Informationen. Attribute können anbieterspezifisch sein. Ein Compiler kann diese Informationen verwenden, um Informationsmeldungen zu generieren oder spezielle Logik beim Kompilieren des attributierten Codes anzuwenden. Der Compiler ignoriert alle Attribute, die nicht erkannt werden, was bedeutet, dass Sie ihre eigenen benutzerdefinierten Attribute nicht mithilfe dieser Syntax definieren können. Attribute werden durch doppelte eckige Klammern eingeschlossen:

[[deprecated]]
void Foo(int);

Attribute stellen eine standardisierte Alternative zu anbieterspezifischen Erweiterungen wie #pragma Direktiven, __declspec() (Visual C++) oder __attribute__ (GNU) dar. Sie müssen jedoch weiterhin die anbieterspezifischen Konstrukte für die meisten Zwecke verwenden. Der Standard gibt derzeit die folgenden Attribute an, die ein konformer Compiler erkennen soll.

[[carries_dependency]]

Das [[carries_dependency]] Attribut gibt an, dass die Funktion die Datenabhängigkeitsordnung für die Threadsynchronisierung verteilt. Das Attribut kann auf einen oder mehrere Parameter angewendet werden, um anzugeben, dass das übergebene Argument eine Abhängigkeit im Funktionstext trägt. Das Attribut kann auf die Funktion selbst angewendet werden, um anzugeben, dass der Rückgabewert eine Abhängigkeit von der Funktion trägt. Der Compiler kann diese Informationen verwenden, um effizienteren Code zu generieren.

[[deprecated]]

Visual Studio 2015 und höher: Das [[deprecated]] Attribut gibt an, dass eine Funktion nicht für die Verwendung vorgesehen ist. Oder dass es in zukünftigen Versionen einer Bibliotheksschnittstelle möglicherweise nicht vorhanden ist. Das [[deprecated]] Attribut kann auf die Deklaration einer Klasse, einen Typedef-Namen, eine Variable, ein nicht statisches Datenelement, eine Funktion, einen Namespace, eine Enumeration, eine Enumeration oder eine Vorlagenspezialisierung angewendet werden. Der Compiler kann dieses Attribut verwenden, um eine Informationsmeldung zu generieren, wenn Clientcode versucht, die Funktion aufzurufen. Wenn der Microsoft C++-Compiler die Verwendung eines [[deprecated]] Elements erkennt, löst er die Compilerwarnung C4996 aus.

[[fallthrough]]

Visual Studio 2017 und höher: (Verfügbar mit /std:c++17 und höher.) Das [[fallthrough]] Attribut kann im Kontext von switch Anweisungen als Hinweis auf den Compiler (oder jeder, der den Code liest) verwendet werden, dass das Fallthrough-Verhalten beabsichtigt ist. Der Microsoft C++-Compiler warnt derzeit nicht über das Verhalten von Fallthrough, sodass dieses Attribut keine Auswirkungen auf das Compilerverhalten hat.

[[likely]]

Visual Studio 2019, Version 16.6 und höher: (Verfügbar mit /std:c++20 und höher.) Das [[likely]] Attribut gibt einen Hinweis an den Compiler an, dass der Codepfad für die attributierten Bezeichnung oder Anweisung wahrscheinlicher ausgeführt wird als Alternativen. Im Microsoft-Compiler markiert das [[likely]] Attribut Blöcke als "Hot Code", wodurch eine interne Optimierungsbewertung erhöht wird. Die Bewertung wird bei der Optimierung für geschwindigkeitsoptimiert und bei der Größenoptimierung nicht so viel erhöht. Die Nettobewertung wirkt sich auf die Wahrscheinlichkeit von Inlining- und Loop-Unrolling-Optimierungen und Vektorisierungsoptimierungen aus. Die Auswirkung [[likely]] und [[unlikely]] ähnelt der profilgeführten Optimierung, aber beschränkt auf den Umfang der aktuellen Übersetzungseinheit. Die Optimierung der Blockneuanordnung wird für dieses Attribut noch nicht implementiert.

[[maybe_unused]]

Visual Studio 2017, Version 15.3 und höher: (Verfügbar mit /std:c++17 und höher.) Das [[maybe_unused]] Attribut gibt an, dass eine Variable, Funktion, Klasse, Typedef, nicht statische Datenmemmemm, Enumeration oder Vorlagenspezialisierung absichtlich nicht verwendet werden kann. Der Compiler warnt nicht, wenn eine entität, die markiert [[maybe_unused]] ist, nicht verwendet wird. Eine Entität, die ohne das Attribut deklariert wird, kann später mit dem Attribut neu deklariert werden und umgekehrt. Eine Entität wird nach der ersten Deklaration, die markiert [[maybe_unused]] ist, als markiert betrachtet und für den Rest der aktuellen Übersetzungseinheit.

[[nodiscard]]

Visual Studio 2017, Version 15.3 und höher: (Verfügbar mit /std:c++17 und höher.) Gibt an, dass der Rückgabewert einer Funktion nicht aufgehoben werden soll Karte. Löst Warnung C4834 aus, wie in diesem Beispiel gezeigt:

[[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]]

Das [[noreturn]] Attribut gibt an, dass eine Funktion niemals zurückgegeben wird, d. h., sie löst immer eine Ausnahme aus oder beendet. Der Compiler kann seine Kompilierungsregeln für [[noreturn]] Entitäten anpassen.

[[unlikely]]

Visual Studio 2019, Version 16.6 und höher: (Verfügbar mit /std:c++20 und höher.) Das [[unlikely]] Attribut gibt einen Hinweis an den Compiler an, dass der Codepfad für die attributierten Bezeichnung oder Anweisung weniger ausgeführt werden kann als Alternativen. Im Microsoft-Compiler markiert das [[unlikely]] Attribut Blöcke als "kalter Code", wodurch eine interne Optimierungsbewertung erhöht wird. Die Bewertung wird bei der Optimierung für Die Größe erhöht und nicht so viel, wenn sie für Geschwindigkeit optimiert wird. Die Nettobewertung wirkt sich auf die Wahrscheinlichkeit von Inlining- und Loop-Unrolling-Optimierungen und Vektorisierungsoptimierungen aus. Die Optimierung der Blockneuanordnung wird für dieses Attribut noch nicht implementiert.

Microsoft-spezifische Attribute

[[gsl::suppress(rules)]]

Das microsoftspezifische [[gsl::suppress(rules)]] Attribut wird verwendet, um Warnungen von Prüfern zu unterdrücken, die Richtlinien-Supportbibliotheksregeln (GSL) im Code erzwingen. Betrachten Sie beispielsweise diesen Codeausschnitt:

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
    }
}

Im Beispiel werden die folgenden Warnungen ausgelöst:

  • C26494 (Typ Rule 5: Always initialize an object.)

  • C26485 (Bounds Rule 3: No array to pointer decay.)

  • C26481 (Begrenzungsregel 1: Verwenden Sie keine Zeigerarithmetik. Verwenden Sie stattdessen Span.)

Die ersten beiden Warnungen werden ausgelöst, wenn Sie diesen Code mit dem installierten und aktivierten CppCoreCheck-Codeanalysetool kompilieren. Die dritte Warnung wird jedoch aufgrund des Attributs nicht ausgelöst. Sie können das gesamte Begrenzungsprofil unterdrücken, indem Sie schreiben [[gsl::suppress(bounds)]] , ohne eine bestimmte Regelnummer einzugeben. Die C++-Kernrichtlinien sind so konzipiert, dass Sie besseren und sichereren Code schreiben können. Das Suppress-Attribut erleichtert das Deaktivieren der Warnungen, wenn sie nicht gewünscht werden.

[[msvc::flatten]]

Das microsoftspezifische Attribut [[msvc::flatten]] ist sehr ähnlich wie [[msvc::forceinline_calls]], und kann an denselben Stellen und auf die gleiche Weise verwendet werden. Der Unterschied besteht darin, dass [[msvc::flatten]][[msvc::forceinline_calls]] alle Aufrufe im Bereich, auf den sie rekursiv angewendet werden, bis keine Aufrufe verbleiben. Dies kann Folgen für das resultierende Größenwachstum der Codegröße der Funktion oder den Durchsatz des Compilers haben, den Sie manuell verwalten müssen.

[[msvc::forceinline]]

Wenn vor einer Funktionsdeklaration platziert wird, hat das microsoftspezifische Attribut [[msvc::forceinline]] die gleiche Bedeutung wie __forceinline.

[[msvc::forceinline_calls]]

Das microsoftspezifische Attribut [[msvc::forceinline_calls]] kann auf oder vor einer Anweisung oder einem Block platziert werden. Die Inline-Heuristik versucht, alle Aufrufe in dieser Anweisung oder Blockierung auszuführen [[msvc::forceinline]] :

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

Der erste Aufruf von foo, und beide Aufrufe baran , werden behandelt, als ob sie deklariert __forceinlinewurden. Der zweite Aufruf wird foo nicht als __forceinlinebehandelt.

[[msvc::intrinsic]]

Das [[msvc::intrinsic]] Attribut weist drei Einschränkungen für die Funktion auf, auf die es angewendet wird:

  • Die Funktion kann nicht rekursiv sein; Der Textkörper darf nur über eine Rückgabe-Anweisung mit einem static_cast vom Parametertyp bis zum Rückgabetyp verfügen.
  • Die Funktion kann nur einen einzelnen Parameter akzeptieren.
  • Die /permissive- Compileroption ist erforderlich. (Die /std:c++20 und späteren Optionen implizieren /permissive- standardmäßig.)

Das microsoftspezifische [[msvc::intrinsic]] Attribut weist den Compiler an, eine Metafunktion inline zu verwenden, die als benannte Umwandlung vom Parametertyp in den Rückgabetyp fungiert. Wenn das Attribut in einer Funktionsdefinition vorhanden ist, ersetzt der Compiler alle Aufrufe dieser Funktion durch eine einfache Umwandlung. Das [[msvc::intrinsic]] Attribut ist in Visual Studio 2022, Version 17.5 Preview 2 und höher, verfügbar. Dieses Attribut gilt nur für die darauf folgende bestimmte Funktion.

Beispiel

In diesem Beispielcode führt das attribut, das [[msvc::intrinsic]] auf die my_move Funktion angewendet wird, zum Ersetzen von Aufrufen der Funktion durch die inlineierte statische Umwandlung im Textkörper:

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]]

Wenn vor einer Funktionsdeklaration platziert wird, hat das microsoftspezifische Attribut [[msvc::noinline]] die gleiche Bedeutung wie declspec(noinline).

[[msvc::noinline_calls]]

Das microsoftspezifische Attribut [[msvc::noinline_calls]] hat dieselbe Verwendung wie [[msvc::forceinline_calls]]. Sie kann vor jeder Anweisung oder einem Block platziert werden. Anstatt alle Aufrufe in diesem Block zu erzwingen, hat sie die Auswirkung, das Inlining für den Bereich zu deaktivieren, auf den sie angewendet wird.

[[msvc::no_tls_guard]]

Das microsoftspezifische [[msvc::no_tls_guard]] Attribut deaktiviert die Überprüfung der Initialisierung beim ersten Zugriff auf threadlokale Variablen in DLLs. Die Überprüfungen sind standardmäßig in Code aktiviert, der mit Visual Studio 2019, Version 16.5 und höheren Versionen erstellt wurde. Dieses Attribut gilt nur für die spezifische Variable, die sie folgt. Verwenden Sie die /Zc:tlsGuards- Compileroption, um Überprüfungen global zu deaktivieren.