close
The Wayback Machine - https://web.archive.org/web/20220104151427/https://es.cppreference.com/w/cpp/language/if
Espacios de nombres
Variantes
Acciones

Instrucción if

De cppreference.com
< cpp‎ | language
 
 
Lenguaje C++
Temas generales
Control de flujo
Instrucciones de ejecución condicionales
if
Instrucciones de iteración (bucles)
Declaraciones de salto
Funciones
Declaración de funciones
Declaración de funciones lambda
Especificador inline
Especificación de excepciones (hasta C++20)
Especificador noexcept (C++11)
Excepciones
Espacios de nombres
Tipos
Especificadores
decltype (C++11)
auto (C++11)
alignas (C++11)
Especificadores de duración de almacenamiento
Inicialización
Expresiones
Representaciones alternas
Literales
Booleanos - Enteros - De punto flotante
De carácter - De cadena - nullptr (C++11)
Definidos por el usuario (C++11)
Utilidades
Atributos (C++11)
Tipos
Declaración de typedef
Declaración de alias de tipo (C++11)
Conversiones
Conversiones implícitas - Conversiones explícitas
static_cast - dynamic_cast
const_cast - reinterpret_cast
Asignación de memoria
Clases
Propiedades de funciones específicas de la clase
Funciones miembro especiales
Plantillas
Misceláneos
 

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
  • una instrucción de expresión (que puede ser una instrucción nula ";")
  • una declaración simple, típicamente una declaración de una variable con un inicializador, pero puede declarar varias variables arbitrarias o ser una declaración de descomposición.
Observa que cualquier instrucción-de-inicialización tiene que terminar con un punto y coma ;, que es la razón por la cual frecuentemente se describe informalmente como una expresión o declaración seguida por un punto y coma.
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 inicializador

Si se usa una instrucción-de-inicialización, la instrucción if es equivalente a:

{
instrucción-de-inicialización
if constexpr(opcional) ( condición )
instrucción-si-verdadero

}

o

{
instruccion-de-inicialización
if constexpr(opcional) ( condición )
instrucción-si-verdadero
else
instrucción-si-falso

}

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 if constexpr se le conoce como la instrucción constexpr if.

En una instrucción constexpr if, el valor de la condición tiene que ser una expresión constante de tipo bool convertida contextualmente. Si el valor es true, entonces instrucción-si-falso se descarta (si está presente), de otra manera, instrucción-si-verdadero se descarta.

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


Nota: un ejemplo donde la condición permanece dependiente del valor después de la creación es una plantilla anidada. Por ejemplo:

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 case, y default:) que aparecen en una sub-instrucción de if en tiempo de compilación (constexpr if) solamente pueden ser citadas (porswitch or goto) dentro de la misma sub-instruccion.

(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

if, else, constexpr

[editar] Véase también

Documentación de C de instrucción if