Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO
✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 192 — #230 ✐ Capítulo 6. Inicialización y limpieza }; G::G(int ii) { i = ii; } int main() { cout > retval; require(retval != 0); int y = retval + 3; G g(y); } ///:~ Puede ver que se ejecuta parte del código, entonces se define >retval, que se usa para capturar datos de la consola, y entonces se definen y y g. C, al contrario, no permite definir una variable en ningún sitio que no sea el comienzo de un bloque. En general, debería definir las variables tan cerca como sea posible del punto en que se usa, e inicializarlas siempre cuando se definen. (Ésta es una sugerencia de estilo para tipos básicos, en los que la inicialización es opcional.) Es una cuestión de seguridad. Reduciendo la duración de disponibilidad al bloque, se reduce la posibilidad de que sea usada inapropiadamente en otra parte del bloque. En resumen, la legibilidad mejora porque el lector no teiene que volver al inicio del bloque para ver el tipo de una variable. 6.3.1. Bucles for En C++, a menudo verá bucles for con el contador definido dentro de la propia expresión. for (int j = 0; j < 100; j++) { cout
✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 193 — #231 ✐ 6.3. Eliminación del bloque de definiciones Hay que tener cuidado con las variables locales que ocultan las variables del ámbito superior. En general, usar el mismo nombre para una variable anidada y una variable que es global en ese ámbito es confuso y propenso a errores 4 Creo que los bloques pequeños son un indicador de un buen diseño. Si una sola función requiere varias páginas, quizá está intentando demasiadas cosas en esa función. Funciones de granularidad más fina no sólo son más útiles, tambíén facilitan la localización de errores. 6.3.2. Alojamiento de memoria Ahora una variable se puede definir en cualquier parte del bloque, podría parecer que el alojamiento para una variable no se puede llevar a cabo hasta el momento en que se define. En realidad, lo más probable es que el compilador siga la práctica de pedir todo el alojamiento para el bloque en la llave de apertura del bloque. No importa porque, como programador, no puede acceder al espacio asociado (es decir, el objeto) hasta que ha sido definido 5 . Aunque el espacio se pida al comienzo del bloque, la llamada al constructor no ocurre hasta el punto en el que se define el objeto ya que el identificador no está disponible hasta entonces. El compilador incluso comprueba que no ponga la definición del objeto (y por tanto la llamada al constructor) en un punto que dependa de una sentencia condicional, como en una sentencia switch o algún lugar que pueda saltar un goto. Descomentar las sentencias del siguiente código generará un error o aviso. //: C06:Nojump.cpp // Can’t jump past constructors class X { public: X(); }; X::X() {} void f(int i) { if(i < 10) { //! goto jump1; // Error: goto bypasses init } X x1; // Constructor called here jump1: switch(i) { case 1 : X x2; // Constructor called here break; //! case 2 : // Error: case bypasses init X x3; // Constructor called here break; } } int main() { f(9); f(11); 4 El lenguaje Java considera esto una idea tan mala que lo considera un error. 5 De acuerdo, probablemente podría trucarlo usando punteros, pero sería muy, muy malo 193 ✐ ✐ ✐ ✐
- Page 179 and 180: ✐ ✐ ✐ “Volumen1” — 2012
- Page 181 and 182: ✐ ✐ ✐ “Volumen1” — 2012
- Page 183 and 184: ✐ ✐ ✐ “Volumen1” — 2012
- Page 185 and 186: ✐ ✐ ✐ “Volumen1” — 2012
- Page 187 and 188: ✐ ✐ ✐ “Volumen1” — 2012
- Page 189 and 190: ✐ ✐ ✐ “Volumen1” — 2012
- Page 191 and 192: ✐ ✐ ✐ “Volumen1” — 2012
- Page 193 and 194: ✐ ✐ ✐ “Volumen1” — 2012
- Page 195 and 196: ✐ ✐ ✐ “Volumen1” — 2012
- Page 197 and 198: ✐ ✐ ✐ “Volumen1” — 2012
- Page 199 and 200: ✐ ✐ ✐ “Volumen1” — 2012
- Page 201 and 202: ✐ ✐ ✐ “Volumen1” — 2012
- Page 203 and 204: ✐ ✐ ✐ “Volumen1” — 2012
- Page 205 and 206: ✐ ✐ ✐ “Volumen1” — 2012
- Page 207 and 208: ✐ ✐ ✐ “Volumen1” — 2012
- Page 209 and 210: ✐ ✐ ✐ “Volumen1” — 2012
- Page 211 and 212: ✐ ✐ ✐ “Volumen1” — 2012
- Page 213 and 214: ✐ ✐ ✐ “Volumen1” — 2012
- Page 215 and 216: ✐ ✐ ✐ “Volumen1” — 2012
- Page 217 and 218: ✐ ✐ ✐ “Volumen1” — 2012
- Page 219 and 220: ✐ ✐ ✐ “Volumen1” — 2012
- Page 221 and 222: ✐ ✐ ✐ “Volumen1” — 2012
- Page 223 and 224: ✐ ✐ ✐ “Volumen1” — 2012
- Page 225 and 226: ✐ ✐ ✐ “Volumen1” — 2012
- Page 227 and 228: ✐ ✐ ✐ “Volumen1” — 2012
- Page 229: ✐ ✐ ✐ “Volumen1” — 2012
- Page 233 and 234: ✐ ✐ ✐ “Volumen1” — 2012
- Page 235 and 236: ✐ ✐ ✐ “Volumen1” — 2012
- Page 237 and 238: ✐ ✐ ✐ “Volumen1” — 2012
- Page 239 and 240: ✐ ✐ ✐ “Volumen1” — 2012
- Page 241 and 242: ✐ ✐ ✐ “Volumen1” — 2012
- Page 243 and 244: ✐ ✐ ✐ “Volumen1” — 2012
- Page 245 and 246: ✐ ✐ ✐ “Volumen1” — 2012
- Page 247 and 248: ✐ ✐ ✐ “Volumen1” — 2012
- Page 249 and 250: ✐ ✐ ✐ “Volumen1” — 2012
- Page 251 and 252: ✐ ✐ ✐ “Volumen1” — 2012
- Page 253 and 254: ✐ ✐ ✐ “Volumen1” — 2012
- Page 255 and 256: ✐ ✐ ✐ “Volumen1” — 2012
- Page 257 and 258: ✐ ✐ ✐ “Volumen1” — 2012
- Page 259 and 260: ✐ ✐ ✐ “Volumen1” — 2012
- Page 261 and 262: ✐ ✐ ✐ “Volumen1” — 2012
- Page 263 and 264: ✐ ✐ ✐ “Volumen1” — 2012
- Page 265 and 266: ✐ ✐ ✐ “Volumen1” — 2012
- Page 267 and 268: ✐ ✐ ✐ “Volumen1” — 2012
- Page 269 and 270: ✐ ✐ ✐ “Volumen1” — 2012
- Page 271 and 272: ✐ ✐ ✐ “Volumen1” — 2012
- Page 273 and 274: ✐ ✐ ✐ “Volumen1” — 2012
- Page 275 and 276: ✐ ✐ ✐ “Volumen1” — 2012
- Page 277 and 278: ✐ ✐ ✐ “Volumen1” — 2012
- Page 279 and 280: ✐ ✐ ✐ “Volumen1” — 2012
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 192 — #230<br />
✐<br />
Capítulo 6. Inicialización y limpieza<br />
};<br />
G::G(int ii) { i = ii; }<br />
int main() {<br />
cout > retval;<br />
require(retval != 0);<br />
int y = retval + 3;<br />
G g(y);<br />
} ///:~<br />
Puede ver que se ejecuta parte del código, <strong>en</strong>tonces se define >retval, que se<br />
usa para capturar datos de la consola, y <strong>en</strong>tonces se defin<strong>en</strong> y y g. C, al contrario, no<br />
permite definir una variable <strong>en</strong> ningún sitio que no sea el comi<strong>en</strong>zo de un bloque.<br />
En g<strong>en</strong>eral, debería definir las variables tan cerca como sea posible del punto <strong>en</strong><br />
que se usa, e inicializarlas siempre cuando se defin<strong>en</strong>. (Ésta es una suger<strong>en</strong>cia de<br />
estilo para tipos básicos, <strong>en</strong> los que la inicialización es opcional.) Es una cuestión de<br />
seguridad. Reduci<strong>en</strong>do la duración de disponibilidad al bloque, se reduce la posibilidad<br />
de que sea usada inapropiadam<strong>en</strong>te <strong>en</strong> otra parte del bloque. En resum<strong>en</strong>, la<br />
legibilidad mejora porque el lector no tei<strong>en</strong>e que volver al inicio del bloque para ver<br />
el tipo de una variable.<br />
6.3.1. Bucles for<br />
En <strong>C++</strong>, a m<strong>en</strong>udo verá bucles for con el contador definido d<strong>en</strong>tro de la propia<br />
expresión.<br />
for (int j = 0; j < 100; j++) {<br />
cout