Pregunta

En C ++, puedes inicializar una variable en una sentencia if, de este modo:

if (CThing* pThing = GetThing())
{
}

¿Por qué uno consideraría este estilo malo o bueno? ¿Cuáles son los beneficios y desventajas?

Personalmente me gusta este estilo porque limita el alcance de la variable pThing, por lo que nunca se puede usar accidentalmente cuando es NULL. Sin embargo, no me gusta que no puedas hacer esto:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

Si hay una manera de hacer que funcione lo anterior, por favor publique. Pero si eso no es posible, todavía me gustaría saber por qué.

Pregunta prestada de aquí, tema similar pero PHP.

¿Fue útil?

Solución

Lo importante es que una declaración en C ++ no es una expresión.

bool a = (CThing* pThing = GetThing()); // not legit!!

No se puede hacer una declaración y una lógica booleana en una sentencia if, la especificación de lenguaje C ++ permite específicamente una expresión o una declaración.

if(A *a = new A)
{
    // this is legit and a is scoped here
}

¿Cómo podemos saber si a está definido entre un término y otro en una expresión?

if((A *a = new A) && a->test())
{
    // was a really declared before a->test?
}

Muerde la bala y use un interno si. Las reglas de alcance son útiles y su lógica es explícita:

if (CThing* pThing = GetThing())
{
    if(pThing->IsReallySomeThing())
    {
    }
}

Otros consejos

Sobre las ventajas:

Siempre se recomienda definir variables cuando las necesite por primera vez, no una línea antes. Esto es para mejorar la legibilidad de su código, ya que se puede saber qué es CThing sin desplazarse y buscar dónde se definió.

También al reducir el alcance a un bloque loop / if, hace que la variable no sea referenciada después de la ejecución del bloque de código, lo que la convierte en una candidata para la recolección de basura (si el idioma admite esta función).

if (CThing* pThing = GetThing())

Es estilo malo , porque dentro del si no está proporcionando una expresión booleana. Usted está proporcionando un CThing * .

CThing* pThing = GetThing();
if (pThing != NULL)

Este es un buen estilo.

Una razón por la que normalmente no hago eso es debido al error común de un '=' perdido en una prueba condicional. Yo uso la pelusa con el error / advertencias establecidas para atraparlos. Entonces gritará sobre todas las asignaciones dentro de los condicionales.

Solo un FYI, creo que algunos de los antiguos que cumplen con Microsoft C ++ (Visual Studios 6 y .NET 2003) no siguen la regla de alcance en algunos casos.

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

Debería estar fuera de alcance, pero ese era / es un código válido. Creo que se jugó como una característica, pero en mi opinión es un incumplimiento. No adherirse a las normas es malo. Solo como desarrollador web sobre IE y Firefox.

¿Puede alguien con VS verificar y ver si sigue siendo válido?

Esta should no funciona en C ++ desde aunque admite evaluación de cortocircuito . Tal vez No intentes lo siguiente:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

err .. vea la respuesta de Wesley Tarle

También puede incluir la asignación en un conjunto adicional de () para evitar el mensaje de advertencia.

Lo veo como algo peligroso. El código a continuación es mucho más seguro y las llaves adjuntas seguirán limitando el alcance de la configuración de la forma que desee.

Supongo que GetThing () a veces devuelve NULL, por lo que puse esa cláusula divertida en la sentencia if (). Evita que se llame a IsReallySomething () en un puntero NULL.

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}

también note que si está escribiendo código C ++, desea que el compilador advierta sobre " = " en una declaración condicional (que no es parte de una declaración) un error.

Es una práctica de codificación aceptable y buena. Sin embargo, las personas que no provienen de un entorno de codificación de bajo nivel probablemente no estén de acuerdo.

Muchas cosas. En primer lugar, punteros desnudos. Por favor evítalos por todos los medios. Utilice referencias, opcional, unique_ptr, shared_ptr. Como último recurso, escriba su propia clase que se ocupe de la propiedad del puntero y nada más.

Use una inicialización uniforme si puede requerir C ++ 11 (C ++ 14 prefiere evitar los defectos de C ++ 11): - evita = vs == confusión y es más estricto en la verificación de los argumentos si hay alguno.

if (CThing thing {})
{
}

Asegúrese de implementar operator bool para obtener una conversión predecible de CThing a bool. Sin embargo, tenga en cuenta que otras personas que lean el código no verán operator bool de inmediato. Las llamadas a métodos explícitos son generalmente más legibles y tranquilizadoras. Si puede requerir C ++ 17, use la sintaxis del inicializador.

if (CThing thing {}; thing.is_good())
{
}

Si C ++ 17 no es una opción, use una declaración de arriba si como han sugerido otros.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top