Instrucción if
Ejecuta otra instrucción de forma condicional.
Se utiliza donde necesita ejecutarse código basado en una condición en tiempo de compilación o en tiempo de ejecución.
Contenido |
[editar] Sintaxis
atrib(opcional) if ( condición ) instrucción-si-verdadero
|
(hasta C++17) | ||||||||
atrib(opcional) if ( condición ) instrucción-si-verdadero else instrucción-si-falso
|
(hasta C++17) | ||||||||
atrib(opcional) if constexpr(opcional) ( instrucción-de-inicialización(opcional) condición ) instrucción-si-verdadero
|
(desde C++17) | ||||||||
atrib(opcional) if constexpr(opcional) ( instrucción-de-inicialización(opcional) condición ) instrucción-si-verdadero else instrucción-si-falso
|
(desde C++17) | ||||||||
| atrib(C++11) | - | cualquier número de atributos |
| condición | - | una de
|
| instrucción-de-inicialización(C++17) | - | ya sea
|
| instrucción-si-verdadero | - | cualquier instrucción (frecuentemente una instrucción compuesta), que se ejecuta si la condición se evalúa como verdadera (true). |
| instrucción-si-falso | - | cualquier instrucción (frecuentemente una instrucción compuesta), que se ejecuta si la condición se evalúa como falsa (false). |
[editar] Explicación
Si la condición produce true después de una conversión a bool, se ejecuta instrucción-si-verdadero.
Si la parte else de la instrucción if está presente y la condición produce false después de una conversión abool, se ejecuta instrucción-si-falso.
En la segunda forma de la instrucción if (la que incluye la parte else), si instrucción-si-verdadero es a su vez una instrucción if, entonces ese if interior también tiene que contener una parte else (en otras palabras, en instrucciones if anidadas, la parte else se asocia con la instrucción if más cercana que no tiene else.
#include <iostream> int main() { // instrucción if sencilla con cláusula else int i = 2; if (i > 2) { std::cout << i << "es mayor que 2\n"; } else { std::cout << i << " no es mayor que 2\n"; } // instrucción if anidada int j = 1; if (i > 1) if (j > 2) std::cout << i << " > 1 y " << j << " > 2\n"; else // esta else es parte de if (j > 2), no de if (i > 1) std::cout << i << " > 1 and " << j << " <= 2\n"; // declaraciones pueden usarse como condiciones con dynamic_cast struct Base { virtual ~Base() {} }; struct Derived : Base { void df() { std::cout << "df()\n"; } }; Base* bp1 = new Base; Base* bp2 = new Derived; if (Derived* p = dynamic_cast<Derived*>(bp1)) // conversión falla, devuelve nullptr p->df(); // no se ejecuta if (auto p = dynamic_cast<Derived*>(bp2)) // conversión tiene éxito p->df(); // se ejecuta }
Salida:
2 no es mayor que 2 2 > 1 y 1 <= 2 df()
Instrucciones if con un inicializadorSi se usa una instrucción-de-inicialización, la instrucción if es equivalente a:
o
Excepto que los nombres declarados por la instruccion-de-inicialización (if instruccion-de-inicialización es una declaración) y los nombres declarados por la condición (la condición if es una declaración) están en el mismo ámbito, que es también el ámbito de ambas instruccioness. std::map<int, std::string> m; std::mutex mx; extern bool shared_flag; // protegido por mx int demo() { if (auto it = m.find(10); it != m.end()) { return it->second.size(); } if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; } if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; } if (int s; int count = ReadBytesWithSignal(&s)) { publish(count); raise(s); } if (auto keywords = {"if", "for", "while"}; std::any_of(keywords.begin(), keywords.end(), [&s](const char* kw) { return s == kw; })) { std::cerr << "Signo no debe ser una palabra clave.\n"; } } |
(desde C++17) | ||||||||||||||||||||||||||||||||||||||||||||||
|
Si se entra a instrucción-si-verdadero mediante una instrucción goto o longjmp, instrucción-si-verdadero no se ejecuta. |
(desde C++14) |
|
No se permite a las instrucciones switch y goto saltar a una rama de una instrucción constexpr if. |
(desde C++17) |
If en tiempo de compilación (constexpr if)A la instrucción que comienza con En una instrucción constexpr if, el valor de la condición tiene que ser una expresión constante de tipo Las instrucciones return en una instrucción descartada no participan en la deducción del tipo de retorno de la función: template <typename T> auto get_value(T t) { if constexpr (std::is_pointer_v<T>) return *t; // deduce tipo de retorno como int para T = int* else return t; // deduce tipo de retorno como int para T = int } La instrucción descartada puede hacer uso odr de una variable que no está definida: extern int x; // no se requiere una definición de x int f() { if constexpr (true) return 0; else if (x) return x; else return -x; } Si una instrucción constexpr if aparece dentro de una entidad emplantillada, y si la condición no es dependiente de valor después de la creación, la instrucción descartada no se crea cuando se crea la plantilla que la cerca. template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) { // ... tratar con p if constexpr (sizeof...(rs) > 0) g(rs...); // nunca se crea con una lista de argumentos vacía. } Fuera de una plantilla, la instrucción descartada se comprueba en su totalidad. if constexpr no es un substituto para la directiva #if del preprocesador: void f() { if constexpr(false) { int i = 0; int *p = i; // ERROR aún en la instrucción descartada } }
template<class T> void g() { auto lm = [](auto p) { if constexpr (sizeof(T) == 1 && sizeof p == 1) { // esta condición permanece dependiente de valor después de la creación de g<T> } }; } Nota la instrucción descartada no puede estar malformada para cada especialización posible: template <typename T> void f() { if constexpr (std::is_arithmetic_v<T>) // ... else static_assert(false, "Tiene que ser aritmetico"); // Malformado: inválido para toda T } La solución alterna común para tal instrucción general es una expresión dependiente de tipo que es siempre falsa: template<class T> struct dependent_false : std::false_type {}; template <typename T> void f() { if constexpr (std::is_arithmetic_v<T>) // ... else static_assert(dependent_false<T>::value, "Tiene que ser aritmetico"); // de acuerdo } Las etiquetas (destinos de goto, las etiquetas |
(desde C++17) |
[editar] Notas
Si instrucción-si-verdadero o instrucción-si-falso no son instrucciones compuestas, se tratan como si lo fueran:
if (x) int i; // i ya no se encuentra en ámbito
es lo mismo que
if (x) { int i; } // i ya no se encuentra en ámbito
El ámbito del nombre introducido por la condición, si es una declaración, es el ámbito combinado de los cuerpos de ambas instrucciones:
if (int x = f()) { int x; // error: redeclaración de x } else { int x; // error: redeclaración de x }
[editar] Palabras clave
[editar] Véase también
| Documentación de C de instrucción if
|

