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 390 — #428 ✐ Capítulo 13. Creación dinámica de objetos La forma de reemplazar el manejador de new-handler por defecto consiste en incluir el archivo new.h y hacer una llamada a la función set_new_handler() con la dirección de la función que se desea instalar: //: C13:NewHandler.cpp // Changing the new-handler #include #include #include using namespace std; int count = 0; void out_of_memory() { cerr
✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 391 — #429 ✐ 13.3. new y delete para vectores re. Frecuentemente la razón para cambiar el asignador es la eficiencia; puede que se necesite crear y destruir tantos objetos de la misma clase que lo haga ineficaz en términos de velocidad: un cuello de botella. En C++ es posible sobrecargar new y d- elete para implementar un esquema particular más adecuado que permita manejar situaciones como ésta. Otra cuestión es la fragmentación del montículo. Cuando los objetos tienen tamaños diferentes es posible llegar a dividir de tal modo el área de memoria libre que se vuelva inútil. Es decir, el espacio puede estar disponible, pero debido al nivel de fragmentación alcanzado, no exista ningún bloque del tamaño requerido. Es posible asegurarse de que esto no llegue a ocurrir mediante la creación de un asignador para una clase específica. En los sistemas de tiempo real y en los sistemas integrados, suele ser necesario que los programas funcionen por largo tiempo con recursos muy limitados. Tales sistemas pueden incluso requerir que cada asignación tome siempre la misma cantidad de tiempo, y que no esté permitida la fragmentación ni el agotamiento en el área dinámica. La solución a este problema consiste en utilizar un asignador «personalizado»; de otro modo, los programadores evitarían usar new y delete es estos casos y desperdiciarían un recurso muy valioso de C++. A la hora de sobrecargar operator new() y operator delete() es importante tener en cuenta que lo único que se está cambiando es la forma en que se realiza la asignación del espacio. El compilador llamará a la nueva versión de new en lugar de al original, para asignar espacio, llamando después al constructor que actuará sobre él. Así que, aunque el compilador convierte una expresión new en código para asignar el espacio y para llamar al constructor, todo lo que se puede cambiar al sobrecargar new es la parte correspondiente a la asignación. delete tiene una limitación similar. Cuando se sobrecarga operator new(), se está reemplazando también el modo de tratar los posibles fallos en la asignación de la memoria. Se debe decidir qué acciones va a realizar en tal caso: devolver cero, un bucle de reintento con llamada al new-handler, o lo que es más frecuente, disparar una excepción bad_alloc (tema que se trata en el Volumen 2). La sobrecarga de new y delete es como la de cualquier otro operador. Existe la posibilidad de elegir entre sobrecarga global y sobrecarga para una clase determinada. Sobrecarga global de new y delete Este es el modo más drástico de abordar el asunto, resulta útil cuando el comportamiento de new y delete no es satisfactorio para la mayor parte del sistema. Al sobrecargar la versión global, quedan inaccesibles las originales, y ya no es posible llamarlas desde dentro de las funciones sobrecargadas. El new sobrecargado debe tomar un argumento del tipo size_t (el estándar de C) para tamaños. Este argumento es generado y pasado por el compilador, y se refiere al tamaño del objeto para el que ahora tenemos la responsabilidad de la asignación de memoria. Debe devolver un puntero a un bloque de ese tamaño, (o mayor, si hubiera motivos para hacerlo así), o cero en el caso de no se encontrara un bloque adecuado. Si eso sucede, no se producirá la llamada al constructor. Por supuesto, hay que hacer algo más informativo que sólo devolver cero, por ejemplo llamar al «new-handler» o disparar una excepción, para indicar que hubo un problema. El valor de retorno de operator new() es void*, no un puntero a un tipo particular. Lo que hace es obtener un bloque de memoria, no un objeto definido, no hasta 391 ✐ ✐ ✐ ✐
- Page 377 and 378: ✐ ✐ ✐ “Volumen1” — 2012
- Page 379 and 380: ✐ ✐ ✐ “Volumen1” — 2012
- Page 381 and 382: ✐ ✐ ✐ “Volumen1” — 2012
- Page 383 and 384: ✐ ✐ ✐ “Volumen1” — 2012
- Page 385 and 386: ✐ ✐ ✐ “Volumen1” — 2012
- Page 387 and 388: ✐ ✐ ✐ “Volumen1” — 2012
- Page 389 and 390: ✐ ✐ ✐ “Volumen1” — 2012
- Page 391 and 392: ✐ ✐ ✐ “Volumen1” — 2012
- Page 393 and 394: ✐ ✐ ✐ “Volumen1” — 2012
- Page 395 and 396: ✐ ✐ ✐ “Volumen1” — 2012
- Page 397 and 398: ✐ ✐ ✐ “Volumen1” — 2012
- Page 399 and 400: ✐ ✐ ✐ “Volumen1” — 2012
- Page 401 and 402: ✐ ✐ ✐ “Volumen1” — 2012
- Page 403 and 404: ✐ ✐ ✐ “Volumen1” — 2012
- Page 405 and 406: ✐ ✐ ✐ “Volumen1” — 2012
- Page 407 and 408: ✐ ✐ ✐ “Volumen1” — 2012
- Page 409 and 410: ✐ ✐ ✐ “Volumen1” — 2012
- Page 411 and 412: ✐ ✐ ✐ “Volumen1” — 2012
- Page 413 and 414: ✐ ✐ ✐ “Volumen1” — 2012
- Page 415 and 416: ✐ ✐ ✐ “Volumen1” — 2012
- Page 417 and 418: ✐ ✐ ✐ “Volumen1” — 2012
- Page 419 and 420: ✐ ✐ ✐ “Volumen1” — 2012
- Page 421 and 422: ✐ ✐ ✐ “Volumen1” — 2012
- Page 423 and 424: ✐ ✐ ✐ “Volumen1” — 2012
- Page 425 and 426: ✐ ✐ ✐ “Volumen1” — 2012
- Page 427: ✐ ✐ ✐ “Volumen1” — 2012
- Page 431 and 432: ✐ ✐ ✐ “Volumen1” — 2012
- Page 433 and 434: ✐ ✐ ✐ “Volumen1” — 2012
- Page 435 and 436: ✐ ✐ ✐ “Volumen1” — 2012
- Page 437 and 438: ✐ ✐ ✐ “Volumen1” — 2012
- Page 439 and 440: ✐ ✐ ✐ “Volumen1” — 2012
- Page 441 and 442: ✐ ✐ ✐ “Volumen1” — 2012
- Page 443 and 444: ✐ ✐ ✐ “Volumen1” — 2012
- Page 445 and 446: ✐ ✐ ✐ “Volumen1” — 2012
- Page 447 and 448: ✐ ✐ ✐ “Volumen1” — 2012
- Page 449 and 450: ✐ ✐ ✐ “Volumen1” — 2012
- Page 451 and 452: ✐ ✐ ✐ “Volumen1” — 2012
- Page 453 and 454: ✐ ✐ ✐ “Volumen1” — 2012
- Page 455 and 456: ✐ ✐ ✐ “Volumen1” — 2012
- Page 457 and 458: ✐ ✐ ✐ “Volumen1” — 2012
- Page 459 and 460: ✐ ✐ ✐ “Volumen1” — 2012
- Page 461 and 462: ✐ ✐ ✐ “Volumen1” — 2012
- Page 463 and 464: ✐ ✐ ✐ “Volumen1” — 2012
- Page 465 and 466: ✐ ✐ ✐ “Volumen1” — 2012
- Page 467 and 468: ✐ ✐ ✐ “Volumen1” — 2012
- Page 469 and 470: ✐ ✐ ✐ “Volumen1” — 2012
- Page 471 and 472: ✐ ✐ ✐ “Volumen1” — 2012
- Page 473 and 474: ✐ ✐ ✐ “Volumen1” — 2012
- Page 475 and 476: ✐ ✐ ✐ “Volumen1” — 2012
- Page 477 and 478: ✐ ✐ ✐ “Volumen1” — 2012
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 390 — #428<br />
✐<br />
Capítulo 13. Creación dinámica de objetos<br />
La forma de reemplazar el manejador de new-handler por defecto consiste <strong>en</strong> incluir<br />
el archivo new.h y hacer una llamada a la función set_new_handler() con<br />
la dirección de la función que se desea instalar:<br />
//: C13:NewHandler.cpp<br />
// Changing the new-handler<br />
#include <br />
#include <br />
#include <br />
using namespace std;<br />
int count = 0;<br />
void out_of_memory() {<br />
cerr