Leí que en C ++ 17 podemos inicializar variables en if
declaraciones como esta
if (int length = 2; length == 2)
//execute something
En vez de
int length = 2;
if (length == 2)
//do something
Aunque es más corto, afecta la legibilidad del código (especialmente para las personas que no conocen esta nueva característica), lo que supongo que es una mala práctica de codificación para el desarrollo de software grande.
¿Existe alguna ventaja de utilizar esta función además de acortar el código?
if (int length = 2; length == 2)
es quizás sorprendente que lo veas la primera vez, pero no es nada complejo que uno no pueda entender, así que ya la segunda vez ya no será una gran sorpresa y declarar cosas en el ámbito al que pertenece es uno de los principales factores que contribuyen a la legibilidad. En mi humilde opinión que su premisa es equivocada;)Respuestas:
Limita el alcance de
length
alif
solo. De modo que obtiene los mismos beneficios que obtuvimos originalmente cuando se nos permitió escribirfor(int i = 0; i < ... ; ++i) { // ... }
En lugar de la variable goteando
int i; for(i = 0; i < ... ; ++i) { // ... }
Las variables de corta duración son mejores por varias razones. Pero para nombrar un par:
Cuanto más tiempo dure algo, menos cosas debe tener en cuenta al leer líneas de código no relacionadas. Si
i
no existe fuera del ciclo oif
declaración, entonces no necesitamos preocuparnos por su valor fuera de ellos. Tampoco debemos preocuparnos de que su valor interactúe con otras partes del programa que están fuera de su alcance previsto (lo que puede suceder si loi
anterior se reutiliza en otro ciclo). Hace que el código sea más fácil de seguir y razonar.Si la variable contiene un recurso, ese recurso ahora se mantiene durante el período más breve posible. Y esto sin llaves extrañas. También se deja en claro que el recurso está relacionado
if
solo. Considere esto como un ejemplo motivadorif(std::lock_guard _(mtx); guarded_thing.is_ready()) { }
Si sus colegas no conocen la función, enséñeles. Apaciguar a los programadores que no desean aprender es una mala excusa para evitar funciones.
fuente
if (auto p = ptr.lock(); p && p->foo()) bar(*p);
{int i = 2; if (i == 2) {...}}
" (Tenga en cuenta el alcance adicional).Reduces el alcance variable. Esto tiene sentido y aumenta la legibilidad, ya que fortalece la localidad de identificadores sobre los que necesita razonar. Estoy de acuerdo en que
if
deben evitarse las declaraciones de inicio largas dentro de las declaraciones, pero para las cosas cortas, está bien.Tenga en cuenta que ya puede realizar la inicialización y la ramificación en el resultado en pre-C ++ 17:
int *get(); // returns nullptr under some condition if (int *ptr = get()) doStuff();
Esto está sujeto a la opinión personal de cada uno, pero puede considerar una condición explícita más legible:
if (int *ptr = get(); ptr != nullptr) doStuff();
Además, argumentar en contra de la legibilidad de una característica refiriéndose al hecho de que la gente no está acostumbrada a ella es peligroso. La gente no estaba acostumbrada a los consejos inteligentes en algún momento, sin embargo, todos estamos de acuerdo hoy (supongo) en que es bueno que estén allí.
fuente
if (auto p =get ())
ya que el operador bool está definidoLa nueva forma de la instrucción if tiene muchos usos.
Propuesta estándar abierta para declaración If con inicializador
Entonces, en resumen, esta declaración simplifica los patrones de código comunes y ayuda a los usuarios a mantener los alcances ajustados.
¡Espero que ayude!
fuente
Con el fin de minimizar el alcance de las variables, existe un idioma que define un recurso solo si es válido en el momento de la creación (por ejemplo , objetos de flujo de archivos ):
if(auto file = std::ifstream("filename")) { // use file here } else { // complain about errors here } // The identifier `file` does not pollute the wider scope
A veces, desea poder revertir la lógica de esa prueba para hacer que la falla sea la cláusula principal y el recurso válido la
else
cláusula. Anteriormente, esto no era posible. Pero ahora podemos hacer:if(auto file = std::ifstream("filename"); !file) { // complain about errors here } else { // use file here }
Un ejemplo podría lanzar una excepción:
if(auto file = std::ifstream(filename); !file) throw std::runtime_error(std::strerror(errno)); else { // use file here }
A algunas personas les gusta codificar para que una función se interrumpa al principio de un error y progrese. Este modismo pone la lógica del aborto físicamente por encima de la lógica de continuación que algunas personas pueden encontrar más natural.
fuente
Es especialmente útil para eventos lógicos. Considere este ejemplo:
char op = '-'; if (op != '-' && op != '+' && op != '*' && op != '/') { std::cerr << "bad stuff\n"; }
Parece un poco duro. A menos que esté muy familiarizado con las
OR, AND
negaciones, es posible que deba hacer una pausa y pensar en esta lógica, que generalmente es un diseño deficiente. Con elif-initialization
puedes sumar expresividad.char op = '-'; if (bool op_valid = (op == '-') || (op == '+') || (op == '*') || (op == '/'); !op_valid) { std::cerr << "bad stuff\n"; }
la variable nombrada también se puede reutilizar dentro del
if
. P.ej:if (double distance = std::sqrt(a * a + b * b); distance < 0.5){ std::cerr << distance << " is too small\n"; }
Esto es genial, especialmente dado que la variable tiene alcance y, por lo tanto, no contamina el espacio después.
fuente
Esta es una extensión de una función existente, que ayuda a la legibilidad en mi experiencia.
if (auto* ptr = get_something()) { }
Aquí ambos creamos la variable
ptr
y probamos que no sea nula. El alcance deptr
se limita a donde es válido. Es mucho, mucho más fácil convencerse a sí mismo de que todo uso deptr
es válido.Pero, ¿qué pasa si estamos hablando de algo que no se convierte de
bool
esa manera?if (auto itr = find(bob)) { }
Eso no funciona. Pero con esta nueva función podemos:
if (auto itr = find(bob); itr != end()) { }
Agregue una cláusula que diga "cuándo es válida esta inicialización".
En esencia, esto nos da un conjunto de tokens que significan "inicializar alguna expresión, y cuando sea válida, hacer algún código. Cuando no sea válida, deséchela".
Ha sido idiomático hacer el truco de la prueba de puntero desde C ++ 98. Una vez que hayas aceptado eso, esta extensión es natural.
fuente