Expressions
Una expresión es una secuencia de operadores y sus operandos , que especifica un cálculo.
La evaluación de expresiones puede producir un resultado (por ejemplo, la evaluación de 2 + 2 produce el resultado 4 ) y puede generar efectos secundarios (por ejemplo, la evaluación de std:: printf ( "%d" , 4 ) imprime el carácter '4' en la salida estándar).
Cada expresión en C++ se caracteriza por dos propiedades independientes: un tipo y una categoría de valor.
Contenidos |
General
- categorías de valor (lvalue, rvalue , glvalue, prvalue, xvalue (desde C++11) ) clasifican expresiones por sus valores
- orden de evaluación de argumentos y subexpresiones especifica el orden en que se obtienen los resultados intermedios
Operadores
| Operadores comunes | ||||||
|---|---|---|---|---|---|---|
| asignación |
incremento
decremento |
aritmética | lógica | comparación |
acceso a
miembros |
otros |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
llamada a función
a ( ... ) |
|
coma
a, b |
||||||
|
condicional
a ? b : c |
||||||
| Operadores especiales | ||||||
|
static_cast
convierte un tipo a otro tipo relacionado
|
||||||
- operator precedence define el orden en el que los operadores se vinculan a sus argumentos
- alternative representations son representaciones alternativas para algunos operadores
- operator overloading permite especificar el comportamiento de los operadores con clases definidas por el usuario.
Conversiones
- conversiones estándar conversiones implícitas de un tipo a otro
-
const_castconversión -
static_castconversión -
dynamic_castconversión -
reinterpret_castconversión - conversión explícita conversión usando notación de conversión estilo C y notación estilo función
- conversión definida por el usuario permite especificar conversión desde clases definidas por el usuario
Asignación de memoria
- expresión new asigna memoria dinámicamente
- expresión delete desasigna memoria dinámicamente
Otros
- expresiones constantes pueden evaluarse en tiempo de compilación y usarse en contexto de compilación (argumentos de plantilla, tamaños de arreglo, etc)
-
sizeof -
alignof -
typeid - expresión throw
Expresiones primarias
Los operandos de cualquier operador pueden ser otras expresiones o expresiones primarias (por ejemplo, en 1 + 2 * 3 , los operandos del operator+ son la subexpresión 2 * 3 y la expresión primaria 1 ).
Las expresiones primarias son cualquiera de las siguientes:
-
this - literales (por ejemplo 2 o "Hello, world" )
-
expresiones de identificador, incluyendo
- identificadores no calificados adecuadamente declarados (por ejemplo n o cout ),
- identificadores calificados adecuadamente declarados (por ejemplo std::string::npos ), y
- identificadores por declarar en declaradores
| (desde C++26) |
| (desde C++11) | |
| (desde C++17) | |
| (desde C++20) |
Cualquier expresión entre paréntesis también se clasifica como una expresión primaria: esto garantiza que los paréntesis tengan mayor precedencia que cualquier operador. Los paréntesis preservan el valor, el tipo y la categoría de valor.
Literales
Los literales son los tokens de un programa C++ que representan valores constantes incrustados en el código fuente.
- literales enteros son números decimales, octales, hexadecimales o binarios de tipo entero.
- literales de carácter son caracteres individuales de tipo
-
- char o wchar_t
|
(desde C++11) |
|
(desde C++20) |
- literales de punto flotante son valores de tipo float , double , o long double
- literales de cadena son secuencias de caracteres de tipo
-
- const char [ ] o const wchar_t [ ]
|
(desde C++11) |
|
(desde C++20) |
- literales booleanos son valores de tipo bool , es decir true y false
|
(desde C++11) |
Expresiones completas
Una expresión constituyente se define de la siguiente manera:
- La expresión constituyente de una expresión es esa expresión.
- Las expresiones constituyentes de una lista de inicialización entre llaves o de una lista de expresiones (posiblemente entre paréntesis) son las expresiones constituyentes de los elementos de la lista respectiva.
-
Las expresiones constituyentes de un
inicializador
que comienza con
=son las expresiones constituyentes de la cláusula-de-inicializador .
int num1 = 0; num1 += 1; // Caso 1: la expresión constituyente de "num += 1" es "num += 1" int arr2[2] = {2, 22} // Caso 2: las expresiones constituyentes // de "{2, 22}" son "2" y "22" // Caso 3: las expresiones constituyentes de "= {2, 22}" // son las expresiones constituyentes de "{2, 22}" // (es decir, también "2" y "22")
Las subexpresiones inmediatas de una expresión E son
- las expresiones constituyentes de E operandos,
|
(desde C++14) |
|
(desde C++11) |
- cualquier llamada a función que E invoque implícitamente, o
- si E es una llamada a función o invoca implícitamente una función, las expresiones constituyentes de cada argumento por defecto utilizado en la llamada.
Una subexpresión de una expresión E es una subexpresión inmediata de E o una subexpresión de una subexpresión inmediata de E . Nótese que las expresiones que aparecen en el "cuerpo de función" de las expresiones lambda no son subexpresiones de la expresión lambda. (desde C++11)
Las siguientes expresiones son expresiones completas :
| (desde C++20) |
- declaradores de declaraciones simples o inicializadores de miembros , incluyendo las expresiones constituyentes de los inicializadores
- invocaciones de destructores generadas al final del tiempo de vida de objetos distintos de objetos temporales cuyo tiempo de vida no ha sido extendido
|
(desde C++26) |
- expresiones que no son una subexpresión de ninguna otra expresión y que no forman parte de ninguna expresión completa
Si una construcción del lenguaje está definida para producir una llamada implícita de una función, el uso de dicha construcción se considera una expresión para los propósitos de esta definición. Las conversiones aplicadas al resultado de una expresión para satisfacer los requisitos de la construcción del lenguaje en la que aparece la expresión también se consideran parte de la expresión completa.
Para un inicializador, realizar la inicialización de la entidad (incluyendo evaluar inicializadores predeterminados de miembros de un agregado) (desde C++14) también se considera parte de la expresión completa.
Expresiones potencialmente evaluadas
|
Una expresión es potencialmente evaluada a menos que
|
(hasta C++11) | ||
|
Los siguientes operandos son operandos no evaluados , no se evalúan:
Una expresión es potencialmente evaluada a menos que
|
(desde C++11) |
Las expresiones potencialmente evaluadas son ODR-use .
|
Esta sección está incompleta
Razón: ejemplo de operandos no evaluados |
Expresiones de valor descartado
Una expresión de valor descartado es una expresión que se utiliza únicamente por sus efectos secundarios. El valor calculado a partir de dicha expresión se descarta. Tales expresiones incluyen la expresión completa de cualquier sentencia de expresión , el operando izquierdo del operador coma incorporado, o el operando de una expresión de conversión que convierte al tipo void .
Las conversiones de array-a-puntero y función-a-puntero nunca se aplican al valor calculado por una expresión de valor descartado. La conversión de lvalue-a-rvalue se aplica si y solo si la expresión es un glvalue calificado volatile y tiene una de las siguientes formas (significado built-in requerido, posiblemente entre paréntesis):
- expresión de identificación,
- expresión de subíndice de arreglo,
- expresión de acceso a miembro de clase,
- indirección,
- operación de puntero a miembro,
- expresión condicional donde tanto el segundo como el tercer operando son una de estas expresiones,
- expresión coma donde el operando derecho es una de estas expresiones.
Además, si el lvalue es de tipo clase calificado como volátil, se requiere un constructor de copia volátil para inicializar el temporal resultante del rvalue.
|
Si la expresión es un prvalue no void (después de cualquier conversión de lvalue-a-rvalue que pueda haber ocurrido), ocurre materialización temporal .
Los compiladores pueden emitir advertencias cuando una expresión diferente a la conversión a
void
descarta un valor declarado con
|
(desde C++17) |
Equivalencia-de-expresiónUn conjunto de expresiones e1 , e2 , ..., eN son equivalentes en expresión si se cumplen todas las siguientes condiciones:
e1 es equivalente en expresión a e2 si y solo si e1 y e2 son equivalentes en expresión (lo que significa que e2 también es equivalente en expresión a e1 ). |
(desde C++20) |
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 1054 | C++98 |
asignar un valor a una variable volatile podría
resultar en una lectura innecesaria debido a la conversión de lvalue-a-rvalue aplicada al resultado de la asignación |
introducir expresiones de valor descartado
y excluir este caso de la lista de casos que requieren la conversión |
| CWG 1343 | C++98 |
la secuenciación de llamadas a destructores en
inicialización de agregados estaba subespecificada |
las expresiones-completas en inicialización de agregados
están bien especificadas |
| CWG 1383 | C++98 |
la lista de expresiones donde la conversión lvalue-a-rvalue
se aplica a expresiones de valor descartado también cubría operadores sobrecargados |
cubrir solo operadores
con significado incorporado |
| CWG 1576 | C++11 |
las conversiones lvalue-a-rvalue no se aplicaban
a expresiones de valor descartado volatile xvalue |
aplicar la conversión
en este caso |
| CWG 2249 | C++98 |
los identificadores a declarar en declaradores
no eran expresiones-id |
lo son |
| CWG 2431 | C++11 |
las invocaciones de los destructores de temporales que
están ligados a referencias no eran expresiones-completas |
lo son |
Véase también
|
Documentación de C
para
Expresiones
|