Namespaces
Variants

Declarations

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Declaraciones son cómo los nombres se introducen (o reintroducen) en el programa C++. No todas las declaraciones realmente declaran algo, y cada tipo de entidad se declara de manera diferente. Definiciones son declaraciones que son suficientes para usar la entidad identificada por el nombre.

Una declaración es una de las siguientes:

  • Declaración de atributos ( attr ; )
(desde C++11)
  • Declaración vacía ( ; )
  • Una declaración de función sin una decl-specifier-seq :
attr  (opcional) declarator ;
attr - (since C++11) secuencia de cualquier número de atributos
declarator - un declarador de función
Esta declaración debe declarar un constructor, destructor o función de conversión de tipo definida por el usuario conversion function . Solo puede utilizarse como parte de una template declaration , explicit specialization , o explicit instantiation.
  • block-declaration (una declaración que puede aparecer dentro de un bloque ), que, a su vez, puede ser una de las siguientes:
(desde C++11)
(desde C++20)
(desde C++11)
  • declaración simple

Contenidos

Declaración simple

Una declaración simple es una sentencia que introduce, crea y opcionalmente inicializa uno o varios identificadores, típicamente variables.

decl-specifier-seq init-declarator-list  (opcional) ; (1)
attr decl-specifier-seq init-declarator-list ; (2) (desde C++11)
decl-specifier-seq - secuencia de especificadores
init-declarator-list - lista separada por comas de init-declarator s (ver abajo)
attr - secuencia de cualquier número de atributos


init-declarator-list solo puede omitirse al declarar una clase con nombre o una enumeración con nombre.

Una declaración de enlace estructurado también es una declaración simple.

(desde C++17)


La sintaxis de init-declarator se define de la siguiente manera:

declarador inicializador (1)
declarador cláusula-requires  (opcional) especificaciones-contrato  (opcional) (2)
1) Un declarador con un inicializador.
2) Un declarador sin un inicializador.
declarator - un declarator
initializer - un initializer
requires-clause - (since C++20) una requires clause
contract-specs - (since C++26) una lista de function contract specifiers


requires-clause solo puede aparecer si declarator declara una función con plantilla .

(since C++20)

contract-specs solo puede aparecer si declarator declara una función o plantilla de función.

(since C++26)

Especificadores

Especificadores de declaración ( decl-specifier-seq ) es una secuencia de los siguientes especificadores separados por espacios, en cualquier orden:

  • el especificador inline también está permitido en declaraciones de variables.
(desde C++17)
  • el friend especificador, permitido en declaraciones de clases y funciones.
  • el especificador constexpr , permitido únicamente en definiciones de variables, declaraciones de funciones y plantillas de funciones, y la declaración de miembros de datos estáticos de tipo literal.
(desde C++11)
  • el especificador consteval , permitido únicamente en declaraciones de funciones y plantillas de funciones.
  • el especificador constinit , permitido únicamente en la declaración de una variable con duración de almacenamiento estática o de hilo. Como máximo uno de los especificadores constexpr , consteval , y constinit puede aparecer en una decl-specifier-seq .
(desde C++20)
  • especificador de clase de almacenamiento ( register , (hasta C++17) static , thread_local , (desde C++11) extern , mutable ). Solo se permite un especificador de clase de almacenamiento , excepto que thread_local puede aparecer junto con extern o static (desde C++11) .
  • Especificadores de tipo ( type-specifier-seq ), una secuencia de especificadores que nombra un tipo. El tipo de cada entidad introducida por la declaración es este tipo, opcionalmente modificado por el declarador (ver abajo). Esta secuencia de especificadores también es utilizada por type-id . Solo los siguientes especificadores son parte de type-specifier-seq , en cualquier orden:
(desde C++11)
(desde C++26)
(desde C++17)
solo se permite un especificador de tipo en una secuencia de especificadores de declaración, con las siguientes excepciones:
  • const puede combinarse con cualquier especificador de tipo excepto consigo mismo.
  • volatile puede combinarse con cualquier especificador de tipo excepto consigo mismo.
  • signed o unsigned pueden combinarse con char , long , short , o int .
  • short o long pueden combinarse con int .
  • long puede combinarse con double .
  • long puede combinarse con long .
(desde C++11)

Atributos pueden aparecer en decl-specifier-seq , en cuyo caso se aplican al tipo determinado por los especificadores precedentes.

Las repeticiones de cualquier especificador en una decl-specifier-seq , como const static const , o virtual inline virtual son errores , excepto que long puede aparecer dos veces (desde C++11) .

Declaradores

Cada init-declarator en una init-declarator-list S D1, D2, D3 ; se procesa como si fuera una declaración independiente con los mismos especificadores: S D1 ; S D2 ; S D3 ; .

Cada declarador introduce exactamente un objeto, referencia, función o (para declaraciones typedef) alias de tipo, cuyo tipo es proporcionado por decl-specifier-seq y opcionalmente modificado por operadores como & (referencia a) o [ ] (arreglo de) o ( ) (función que retorna) en el declarador. Estos operadores pueden aplicarse recursivamente, como se muestra a continuación.

Un declarador es uno de los siguientes:

unqualified-id attr  (opcional) (1)
qualified-id attr  (opcional) (2)
... identifier attr  (opcional) (3) (desde C++11)
* attr  (opcional) cv  (opcional) declarator (4)
nested-name-specifier * attr  (opcional) cv  (opcional) declarator (5)
& attr  (opcional) declarator (6)
&& attr  (opcional) declarator (7) (desde C++11)
noptr-declarator [ constant-expression  (opcional) ] attr  (opcional) (8)
noptr-declarator ( parameter-list ) cv  (opcional) ref   (opcional) except  (opcional) attr  (opcional) (9)
( declarator ) (10)
1) El name que se declara.
2) Un declarador que utiliza un identificador calificado ( qualified-id ) define o redeclara un miembro de namespace o miembro de clase previamente declarado.
4) Declarador de puntero : la declaración S * D ; declara D como un puntero al tipo determinado por decl-specifier-seq S .
5) Declaración de puntero a miembro : la declaración S C :: * D ; declara D como un puntero a miembro de C de tipo determinado por decl-specifier-seq S . nested-name-specifier es una secuencia de nombres y operadores de resolución de ámbito ::
6) Declarador de referencia Lvalue : la declaración S & D ; declara D como una referencia Lvalue al tipo determinado por decl-specifier-seq S .
7) Declarador de referencia a valor derecho : la declaración S && D ; declara D como una referencia a valor derecho al tipo determinado por decl-specifier-seq S .
8) Declarador de arreglo . noptr-declarator cualquier declarador válido, pero si comienza con *, &, o &&, debe estar rodeado por paréntesis.
9) Declarador de función . noptr-declarator cualquier declarador válido, pero si comienza con *, &, o &&, debe estar rodeado por paréntesis. Puede terminar con el tipo de retorno final opcional. (desde C++11)
10) Declarador entre paréntesis.

En todos los casos, attr es una secuencia opcional de attributes . Cuando aparece inmediatamente después del identificador, se aplica al objeto que se está declarando.

(since C++11)

cv es una secuencia de calificadores const y volatile , donde cada calificador puede aparecer como máximo una vez en la secuencia.

Notas

Cuando una block-declaration aparece dentro de un bloque , y un identificador introducido por una declaración fue previamente declarado en un bloque externo, la declaración externa queda oculta durante el resto del bloque.

Si una declaración introduce una variable con duración de almacenamiento automático, se inicializa cuando se ejecuta su sentencia de declaración. Todas las variables automáticas declaradas en un bloque se destruyen al salir del bloque (independientemente de cómo se abandone el bloque: mediante exception , goto , o al alcanzar su final), en orden inverso a su orden de inicialización.

Ejemplo

Nota: este ejemplo demuestra cómo se analizan algunas declaraciones complejas en términos de la gramática del lenguaje. Otras reglas mnemotécnicas populares son: la regla espiral , lectura de adentro hacia afuera , y la declaración refleja el uso . También existe un analizador automatizado en https://cdecl.org .

#include <type_traits>
struct S
{
    int member;
    // decl-specifier-seq is "int"
    // declarator is "member"
} obj, *pObj(&obj);
// decl-specifier-seq is "struct S { int member; }"
// declarator "obj" declares an object of type S
// declarator "*pObj" declares a pointer to S,
//     and initializer "(&obj)" initializes it
int i = 1, *p = nullptr, f(), (*pf)(double);
// decl-specifier-seq is "int"
// declarator "i" declares a variable of type int,
//     and initializer "= 1" initializes it
// declarator "*p" declares a variable of type int*,
//     and initializer "= nullptr" initializes it
// declarator "f()" declares (but doesn't define)
//     a function taking no arguments and returning int
// declarator "(*pf)(double)" declares a pointer to function
//     taking double and returning int
int (*(*var1)(double))[3] = nullptr;
// decl-specifier-seq is "int"
// declarator is "(*(*var1)(double))[3]"
// initializer is "= nullptr"
// 1. declarator "(*(*var1)(double))[3]" is an array declarator:
//    Type declared is: "(*(*var1)(double))" array of 3 elements
// 2. declarator "(*(*var1)(double))" is a pointer declarator:
//    Type declared is: "(*var1)(double)" pointer to array of 3 elements
// 3. declarator "(*var1)(double)" is a function declarator:
//    Type declared is: "(*var1)" function taking "(double)",
//    returning pointer to array of 3 elements.
// 4. declarator "(*var1)" is a pointer declarator:
//    Type declared is: "var1" pointer to function taking "(double)",
//    returning pointer to array of 3 elements.
// 5. declarator "var1" is an identifier.
// This declaration declares the object var1 of type "pointer to function
// taking double and returning pointer to array of 3 elements of type int"
// The initializer "= nullptr" provides the initial value of this pointer.
// C++11 alternative syntax:
auto (*var2)(double) -> int (*)[3] = nullptr;
// decl-specifier-seq is "auto"
// declarator is "(*var2)(double) -> int (*)[3]"
// initializer is "= nullptr"
// 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator:
//    Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]"
// ...
int main()
{
    static_assert(std::is_same_v<decltype(var1), decltype(var2)>);
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 482 C++98 los declaradores de redeclaraciones no podían estar calificados se permiten declaradores calificados
CWG 569 C++98 un punto y coma independiente no era una declaración válida es una declaración vacía,
que no tiene efecto
CWG 1830 C++98 se permitía la repetición de un especificador de función en una decl-specifier-seq la repetición está prohibida

Véase también

Documentación de C para Declarations