Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
C++ estándar define un conjunto común de atributos. También permite a los proveedores de compiladores definir sus propios atributos dentro de un espacio de nombres específico del proveedor. Sin embargo, los compiladores solo son necesarios para reconocer los atributos definidos en el estándar.
En algunos casos, los atributos estándar se superponen con parámetros __declspec específicos del compilador. En Microsoft C++, puede usar el atributo [[deprecated]] en lugar de usar __declspec(deprecated). Cualquier compilador compatible reconoce el atributo [[deprecated]]. Para todos los demás parámetros __declspec, como dllimport y dllexport, hasta ahora no hay ningún atributo equivalente, por lo que debe seguir usando la sintaxis __declspec. Los atributos no afectan al sistema de tipos y no cambian el significado de un programa. Los compiladores omiten los valores de atributo que no reconocen.
Visual Studio 2017, versión 15.3 y posteriores (disponible con /std:c++17 y versiones posteriores): en el ámbito de una lista de atributos, puede especificar el espacio de nombres de todos los nombres con un único introductor using:
void g() {
[[using rpr: kernel, target(cpu,gpu)]] // equivalent to [[ rpr::kernel, rpr::target(cpu,gpu) ]]
do task();
}
Atributos de C++ estándar
En C++11, los atributos proporcionan una manera estandarizada de anotar construcciones de C++ (incluidas, entre otras, clases, funciones, variables y bloques) con información adicional. Los atributos pueden o no ser específicos del proveedor. Un compilador puede usar esta información para generar mensajes informativos o para aplicar lógica especial al compilar el código con atributos. El compilador omite los atributos que no reconoce, lo que significa que no puede definir sus propios atributos personalizados mediante esta sintaxis. Los atributos se incluyen entre corchetes dobles:
[[deprecated]]
void Foo(int);
Los atributos representan una alternativa estandarizada a extensiones específicas del proveedor, como directivas #pragma, __declspec() (Visual C++) o __attribute__ (GNU). Sin embargo, para la mayoría de los propósitos, tendrá que usar las construcciones específicas del proveedor. El estándar especifica actualmente los siguientes atributos que un compilador compatible debe reconocer.
[[carries_dependency]]
El atributo [[carries_dependency]] especifica que la función propaga el orden de dependencia de datos para la sincronización de subprocesos. El atributo se puede aplicar a uno o varios parámetros para especificar que el argumento pasado lleva una dependencia en el cuerpo de la función. El atributo se puede aplicar a la propia función para especificar que el valor devuelto lleva una dependencia fuera de la función. El compilador puede usar esta información para generar código más eficaz.
[[deprecated]]
Visual Studio 2015 y versiones posteriores: el atributo [[deprecated]] especifica que una función no está pensada para su uso. O bien, es posible que no exista en versiones futuras de una interfaz de biblioteca. El atributo [[deprecated]] se puede aplicar a la declaración de una clase, un typedef-name, una variable, un miembro de datos no estático, una función, un espacio de nombres, una enumeración, un enumerador o una especialización de plantilla. El compilador puede usar este atributo para generar un mensaje informativo cuando el código de cliente intenta llamar a la función. Cuando el compilador de Microsoft C++ detecta el uso de un elemento [[deprecated]], genera la advertencia del compilador C4996.
[[fallthrough]]
Visual Studio 2017 y versiones posteriores: (disponible con /std:c++17 y versiones posteriores). El atributo [[fallthrough]] se puede usar en el contexto de las instrucciones switch como una sugerencia para el compilador (o cualquier persona que lea el código) de que el comportamiento de fallthrough está previsto. Actualmente, el compilador de Microsoft C++ no advierte sobre el comportamiento de paso explícito, por lo que este atributo no tiene ningún efecto sobre el comportamiento del compilador.
[[likely]]
Visual Studio 2019, versión 16.6 y posteriores: (disponible con /std:c++20 y versiones posteriores). El atributo [[likely]] especifica una sugerencia para el compilador que indica que es más probable que se ejecute la ruta de código de la etiqueta o instrucción con atributos que las alternativas. En el compilador de Microsoft, el atributo [[likely]] marca los bloques como "código frecuente", lo que incrementa una puntuación de optimización interna. La puntuación se incrementa más al optimizar la velocidad y no tanto al optimizar el tamaño. La puntuación neta afecta a la probabilidad de insertar, desenrollar bucles y vectorizar optimizaciones. El efecto de [[likely]] y [[unlikely]] es similar a la característica Optimización guiada por perfiles, pero limitado en el ámbito a la unidad de traducción actual. La optimización de reordenación de bloques aún no se ha implementado para este atributo.
[[maybe_unused]]
Visual Studio 2017, versión 15.3 y posteriores: (disponible con /std:c++17 y versiones posteriores). El atributo [[maybe_unused]] especifica que una variable, función, clase, typedef, miembro de datos no estático, enumeración o especialización de plantilla puede no usarse intencionadamente. El compilador no advierte cuando no se usa una entidad marcada como [[maybe_unused]]. Una entidad declarada sin el atributo se puede volver a declarar posteriormente con el atributo y viceversa. Una entidad se considera marcada después de que se analiza su primera declaración marcada como [[maybe_unused]] y para el resto de la unidad de traducción actual.
[[nodiscard]]
Visual Studio 2017, versión 15.3 y posteriores: (disponible con /std:c++17 y versiones posteriores). Especifica que el valor devuelto de una función no está destinado a ser descartado. Genera la advertencia C4834, como se muestra en este ejemplo:
[[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]]
El atributo [[noreturn]] especifica que una función nunca devuelve un valor; en otras palabras, siempre lanza una excepción o se cierra. El compilador puede ajustar sus reglas de compilación para las entidades [[noreturn]].
[[unlikely]]
Visual Studio 2019, versión 16.6 y posteriores: (disponible con /std:c++20 y versiones posteriores). El atributo [[unlikely]] especifica una sugerencia para el compilador que indica que es menos probable que se ejecute la ruta de código de la etiqueta o instrucción con atributos que las alternativas. En el compilador de Microsoft, el atributo [[unlikely]] marca los bloques como "código poco frecuente", lo que reduce una puntuación de optimización interna. La puntuación se reduce más al optimizar el tamaño y no tanto al optimizar la velocidad. La puntuación neta afecta a la probabilidad de insertar, desenrollar bucles y vectorizar optimizaciones. La optimización de reordenación de bloques aún no se ha implementado para este atributo.
Atributos específicos de Microsoft
[[gsl::suppress(<tag> [, justification: <narrow-string-literal>])]]
<tag> es una cadena que especifica el nombre de la regla que se va a suprimir. El campo opcional justification le permite explicar por qué se está desactivando o suprimiendo una advertencia. Este valor aparecerá en la salida de SARIF cuando se especifique la /analyze:log:includesuppressed opción. Su valor es un literal de cadena estrecha codificado en UTF-8. El [[gsl::suppress]] atributo está disponible en Visual Studio 2022, versión 17.14 y versiones posteriores.
El atributo [[gsl::suppress]] específico de Microsoft se usa para suprimir las advertencias de los comprobadores que aplican reglas de la biblioteca de compatibilidad de directrices (GSL) en el código. Por ejemplo, considere este fragmento de código:
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
}
}
En el ejemplo se generan estas advertencias:
C26494 (Regla de tipo 5: Inicializar siempre un objeto).
C26485 (Regla de límites 3: Sin degradación de matriz a puntero).
C26481 (Regla de límites 1: No usar aritmética de punteros. Usar intervalos en su lugar).
Las dos primeras advertencias se activan al compilar este código con la herramienta de análisis de código CppCoreCheck instalada y activada. Pero la tercera advertencia no se desencadena debido al atributo. Puede suprimir todo el perfil de límites escribiendo [[gsl::suppress("bounds")]] sin incluir un número de regla específico. Las directrices de C++ Core Guidelines están diseñadas para ayudarle a escribir código mejor y más seguro. El atributo suppress facilita la desactivación de las advertencias cuando no se desean.
[[msvc::flatten]]
El atributo [[msvc::flatten]] específico de Microsoft es muy similar a [[msvc::forceinline_calls]] y se puede usar en los mismos lugares y de la misma manera. La diferencia es que [[msvc::flatten]][[msvc::forceinline_calls]] todas las llamadas del ámbito a las que se aplica de forma recursiva, hasta que no queden llamadas. Esto puede tener consecuencias para el crecimiento del tamaño de código resultante de la función o el rendimiento del compilador, que debe administrar manualmente.
[[msvc::forceinline]]
Cuando se coloca antes de una declaración de función, el atributo [[msvc::forceinline]] específico de Microsoft tiene el mismo significado que __forceinline.
[[msvc::forceinline_calls]]
El atributo [[msvc::forceinline_calls]] específico de Microsoft se puede colocar en una instrucción o un bloque o antes. Hace que la heurística insertada intente [[msvc::forceinline]] todas las llamadas de esa instrucción o bloque:
void f() {
[[msvc::forceinline_calls]]
{
foo();
bar();
}
...
[[msvc::forceinline_calls]]
bar();
foo();
}
La primera llamada a foo y ambas llamadas a bar se tratan como si se declararan __forceinline. La segunda llamada a foo no se trata como __forceinline.
[[msvc::intrinsic]]
El atributo [[msvc::intrinsic]] tiene tres restricciones en la función a la que se aplica:
- La función no puede ser recursiva; su cuerpo solo debe tener una instrucción return con
static_castdel tipo de parámetro al tipo de valor devuelto. - La función solo puede aceptar un único parámetro.
- La opción del compilador
/permissive-no es necesaria. (Las opciones/std:c++20y posteriores implican/permissive-de forma predeterminada).
El atributo [[msvc::intrinsic]] específico de Microsoft indica al compilador que inserte una metafunción que actúe como una conversión con nombre del tipo de parámetro al tipo de valor devuelto. Cuando el atributo está presente en una definición de función, el compilador reemplaza todas las llamadas a esa función por una conversión simple. El atributo [[msvc::intrinsic]] está disponible en Visual Studio 2022, versión 17.5, versión preliminar 2 y versiones posteriores. Este atributo solo se aplica a la función específica que le sigue.
Ejemplo
En este código de ejemplo, el atributo [[msvc::intrinsic]] aplicado a la función my_move hace que el compilador reemplace las llamadas a la función por la conversión estática insertada en su cuerpo:
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]]
El [[msvc::musttail]] atributo, introducido en MSVC Build Tools versión 14.50, es un atributo experimental específico de Microsoft que aplica la optimización de llamadas finales. Cuando se aplica a una instrucción return apta, indica al compilador que emita la llamada como una llamada final. Si el compilador no puede emitir la llamada de cola, genera un error de compilación. El [[msvc::musttail]] atributo aplica una llamada de cola en lugar de insertar la función.
[[msvc::musttail]] Requisitos:
- El autor de la llamada y el destinatario deben tener tipos de valor devuelto coincidentes.
- Las convenciones de llamada deben ser compatibles.
- La llamada final debe ser la acción final en la función de llamada.
- El destinatario no puede usar más espacio de pila que la función que realiza la llamada.
- Si se pasan más de cuatro parámetros enteros, la función de llamada debe asignar suficiente espacio de pila para esos argumentos adicionales.
- Compile con
/O2o/O2 /GLnivel de optimización.
Ejemplo
Las llamadas finales son una optimización del compilador que es posible cuando una llamada de función es la última acción realizada antes de devolver. En lugar de crear un nuevo marco de pila para llamar a la función, se reutiliza el marco de pila de la función actual. Esto reduce el uso de la pila y mejora el rendimiento, especialmente en escenarios recursivos.
En el código siguiente, el atributo aplicado a return increment(x) hace que el [[msvc::musttail]] control se transfiera directamente a increment. Cuando increment llega a la return x+1; instrucción , su resultado se proporciona directamente al autor de la llamada de incrementIfPositive, que es main. Esto reemplaza la inserción increment en incrementIfPositive o la llamada increment desde y vuelve a incrementIfPositive antes de incrementIfPositive volver a main. La optimización de la llamada final elimina la necesidad de incrementIfPositive recuperar el control después increment de finalizar. Se trata de una optimización del rendimiento que reduce el uso de la pila, especialmente útil en escenarios recursivos.
// 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]]
Cuando se coloca antes de una declaración de función, el atributo [[msvc::noinline]] específico de Microsoft tiene el mismo significado que __declspec(noinline).
[[msvc::noinline_calls]]
El atributo [[msvc::noinline_calls]] específico de Microsoft tiene el mismo uso que [[msvc::forceinline_calls]]. Se puede colocar antes de cualquier instrucción o bloque. En lugar de forzar la inserción de todas las llamadas en ese bloque, tiene el efecto de desactivar la inserción para el ámbito al que se aplica.
[[msvc::no_tls_guard]]
El atributo [[msvc::no_tls_guard]] específico de Microsoft deshabilita las comprobaciones de inicialización en el primer acceso a variables locales de subprocesos en archivos DLL. Las comprobaciones están habilitadas de forma predeterminada en el código compilado con Visual Studio 2019 versión 16.5 y versiones posteriores. Este atributo solo se aplica a la variable específica que le sigue. Para deshabilitar las comprobaciones globalmente, use la opción del compilador /Zc:tlsGuards-.