Source

PensarEnC++ / V1-C13.xml

The branch 'PensarEnC++' does not exist.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 23/PSGML
  Traducción original: Fernando Perfumo Velázquez <nperfumo@telefonica.net>
  Formateado DocBook:  Fernando Perfumo Velázquez <nperfumo@telefonica.net>
  Revisión:            David Villa Alises
-->

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
                 "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">

<chapter
  xmlns:xi="http://www.w3.org/2001/XInclude"
  id="C13">

  <!-- Dynamic Object Creation -->
  <title>Creación dinámica de objetos</title>

  <!--
  Sometimes you know the exact quantity, type, and lifetime of the objects in your
  program. But not always.
  -->
  <highlights>
    <para>
      A veces se conoce exactamente la cantidad, el tipo y el ciclo de vida de los objetos
      de un programa, pero no siempre es así.
    </para>
  </highlights>

  <!--
  How many planes will an air-traffic system need to handle? How many shapes will a CAD
  system use? How many nodes will there be in a network?
  -->
  <para>
    ¿Cuántos aviones tendrá que supervisar un sistema de control de tráfico aéreo?
    ¿Cuántas figuras usará un sistema CAD? ¿Cuántos nodos habrá en una red?
  </para>

  <!--
  To solve the general programming problem, it’s essential that you be able to create and
  destroy objects at runtime. Of course, C has always provided the dynamic memory
  allocation functions malloc( ) and free( ) (along with variants of malloc( )) that
  allocate storage from the heap (also called the free store) at runtime.
  -->
  <para>
    Para resolver un problema general de programación es esencial poder crear y destruir
    objetos en tiempo de ejecución. Por supuesto, C proporciona las funciones de
    asignación dinámica de memoria <function>malloc()</function> y
    <function>free()</function> (y sus variantes), que permiten obtener y liberar bloques
    de espacio de memoria del <emphasis>montículo</emphasis> (también llamado
    <emphasis>almacenamiento libre</emphasis><footnote>
      <para>
	N.T. <foreignphrase>free store</foreignphrase>
      </para>
    </footnote> en tiempo de ejecución.
  </para>

  <!--
  However, this simply won’t work in C++. The constructor doesn’t allow you to hand it the
  address of the memory to initialize, and for good reason. If you could do that, you
  might:
  -->
  <para>
    Sin embargo, este método no funcionará en C++. El constructor no le permite manipular
    la dirección de memoria a inicializar, y por una buena razón. De permitirlo, sería
    posible:
  </para>

  <!--
  1. Forget. Then guaranteed initialization of objects in C++ wouldn't be guaranteed.
  2. Accidentally do something to the object before you initialize it, expecting the right thing to happen.
  3. Hand it the wrong-sized object
  -->
  <orderedlist numeration="arabic">
    <listitem>
      <para>
	Olvidar la llamada al constructor. Con lo cual no sería posible garantizar la
	inicialización de los objetos en C++.
      </para>
    </listitem>
    <listitem>
      <para>
	Usar accidentalmente un objeto que aún no ha sido inicializado, esperando que todo
	vaya bien.
      </para>
    </listitem>
    <listitem>
      <para>
	Manipular un objeto de tamaño incorrecto.
      </para>
    </listitem>
  </orderedlist>


  <!--
  And of course, even if you did everything correctly, anyone who modifies your program is
  prone to the same errors. Improper initialization is responsible for a large portion of
  programming problems, so it’s especially important to guarantee constructor calls for
  objects created on the heap.
  -->
  <para>
    Y por supuesto, incluso si se hizo todo correctamente, cualquiera que modifique el
    programa estaría expuesto a cometer esos mismos errores. Una gran parte de los
    problemas de programación tienen su origen en la inicialización incorrecta de objetos,
    lo que hace especialmente importante garantizar la llamada a los constructores para
    los objetos que se crean en el montículo.
  </para>

  <!--
  So how does C++ guarantee proper initialization and cleanup, but allow you to create
  objects dynamically on the heap?
  -->
  <para>
    ¿Cómo se garantiza en C++ la correcta inicialización y limpieza, permitiendo la
    creación dinámica de objetos?
  </para>

  <!--
  The answer is by bringing dynamic object creation into the core of the language. malloc
  ( ) and free( ) are library functions, and thus outside the control of the compiler.
  However, if you have an operator to perform the combined act of dynamic storage
  allocation and initialization and another operator to perform the combined act of
  cleanup and releasing storage, the compiler can still guarantee that constructors and
  destructors will be called for all objects.
  -->
  <para>
    La respuesta pasa por integrar en el lenguaje mismo la creación dinámica de
    objetos. <function>malloc()</function> y <function>free()</function> son funciones de
    biblioteca y por tanto, están fuera del control del compilador. Si se dispone de un
    <emphasis>operador</emphasis> que lleve a cabo el acto combinado de la asignación
    dinámica de memoria y la inicialización, y de otro operador que realice el acto
    combinado de la limpieza y de liberación de memoria, el compilador podrá garantizar la
    llamada a los constructores y destructores de los objetos.
  </para>

  <!--
  In this chapter, you’ll learn how C++’s new and delete elegantly solve this problem by
  safely creating objects on the heap.
  -->
  <para>
    En este capítulo aprenderá cómo se resuelve de modo elegante este problema con los
    operadores <kw>new</kw> y <kw>delete</kw> de C++.
  </para>

  <sect1>
    <!-- : Object creation -->
    <title>Creación de objetos</title>

    <!-- When a C++ object is created, two events occur: -->
    <para>
      La creación de un objeto en C++ tiene lugar en dos pasos:
    </para>

    <!--
    1. Storage is allocated for the object.
    2. The constructor is called to initialize that storage.
    -->
    <orderedlist numeration="arabic">
      <listitem>
	<para>Asignación de memoria para el objeto.</para>
      </listitem>
      <listitem>
	<para>Llamada al constructor.</para>
      </listitem>
    </orderedlist>

    <!--
    By now you should believe that step two always happens. C++ enforces it because
    uninitialized objects are a major source of program bugs. It doesn’t matter where or
    how the object is created – the constructor is always called.
    -->
    <para>
      Aceptemos por ahora que este segundo paso ocurre <emphasis>siempre</emphasis>. C++
      lo fuerza, debido a que el uso de objetos no inicializados es una de las causas más
      frecuentes de errores de programación. Siempre se invoca al constructor, sin
      importar cómo ni dónde se crea el objeto.
    </para>


    <!-- Step one, however, can occur in several ways, or at alternate times: -->
    <para>
      El primero de estos pasos puede ocurrir de varios modos y en diferente momento:
    </para>

    <!--
    1. Storage can be allocated before the program begins, in the static storage
    area. This storage exists for the life of the program.

    2. Storage can be created on the stack whenever a particular execution point is
    reached (an opening brace). That storage is released automatically at the
    complementary execution point (the closing brace). These stack-allocation operations
    are built into the instruction set of the processor and are very efficient. However,
    you have to know exactly how many variables you need when you’re writing the program
    so the compiler can generate the right code.

    3. Storage can be allocated from a pool of memory called the heap (also known as the
    free store). This is called dynamic memory allocation. To allocate this memory, a
    function is called at runtime; this means you can decide at any time that you want
    some memory and how much you need. You are also responsible for determining when to
    release the memory, which means the lifetime of that memory can be as long as you
    choose – it isn’t determined by scope.
    -->
    <orderedlist numeration="arabic">

      <listitem>
	<para>
	  Asignación de memoria en la zona de almacenamiento estático, que tiene lugar
	  durante la carga del programa.  El espacio de memoria asignado al objeto existe
	  hasta que el programa termine.
	</para>
      </listitem>
      <listitem>
	<para>
	  Asignación de memoria en la pila, cuando se alcanza algún punto determinado
	  durante la ejecución del programa (la llave de apertura de un bloque). La
	  memoria asignada se vuelve a liberar de forma automática en cuanto se alcanza el
	  punto de ejecución complementario (la llave de cierre de un bloque). Las
	  operaciones de manipulación de la pila forman parte del conjunto de
	  instrucciones del procesador y son muy eficientes. Por otra parte, es necesario
	  saber cuantas variables se necesitan mientras se escribe el programa de modo que
	  el copilador pueda generar el código correspondiente.
	</para>
      </listitem>
      <listitem>
	<para>
	  Asignación dinámica, en una zona de memoria libre llamada montículo
	  (<foreignphrase>heap</foreignphrase> o <foreignphrase>free
	  store</foreignphrase>). Se reserva espacio para un objeto en esta zona mediante
	  la llamada a una función durante la ejecución del programa; esto significa que
	  se puede decidir en cualquier momento que se necesita cierta cantidad de
	  memoria. Esto conlleva la responsabilidad de determinar el momento en que ha de
	  liberarse la memoria, lo que implica determinar el tiempo de vida de la misma
	  que, por tanto, ya no está bajo control de las reglas de ámbito.
	</para>
      </listitem>
    </orderedlist>


    <!--
    Often these three regions are placed in a single contiguous piece of physical memory:
    the static area, the stack, and the heap (in an order determined by the compiler
    writer). However, there are no rules. The stack may be in a special place, and the
    heap may be implemented by making calls for chunks of memory from the operating
    system. As a programmer, these things are normally shielded from you, so all you need
    to think about is that the memory is there when you call for it.
    -->
    <para>
      A menudo, las tres regiones de memoria referidas se disponen en una zona contigua de
      la memoria física: área estática, la pila, y el montículo, en un orden determinado
      por el escritor del compilador. No hay reglas fijas. La pila puede estar en una zona
      especial, y puede que las asignaciones en el montículo se obtengan mediante petición
      de bloques de la memoria del sistema operativo. Estos detalles quedan normalmente
      ocultos al programador puesto que todo lo que se necesita conocer al respecto es que
      esa memoria estará disponible cuando se necesite.
    </para>

    <sect2>
      <!-- : C’s approach to the heap -->
      <title>Asignación dinámica en C</title>

      <!--
      To allocate memory dynamically at runtime, C provides functions in its standard
      library:  malloc( ) and its variants calloc( ) and realloc( ) to produce memory from
      the heap, and free( ) to release the memory back to the heap. These functions are
      pragmatic but primitive and require understanding and care on the part of the
      programmer. To create an instance of a class on the heap using C’s dynamic memory
      functions, you’d have to do something like this:
      -->
      <para>
	C proporciona las funciones de su biblioteca estándar
	<function>malloc()</function> y sus variantes <function>calloc()</function> y
	<function>realloc()</function> para asignar, y <function>free()</function> para
	liberar bloques de memoria dinámicamente en tiempo de ejecución. Estas funciones
	son pragmáticas, pero rudimentarias, por lo que requieren comprensión y un
	cuidadoso manejo por parte del programador. El listado que sigue es un ejemplo que
	ilustra el modo de crear una instancia de una clase con estas funciones de C:
      </para>

<!-- REVISANDO AQUI -->

//: V1C13:MallocClass.cpp


      <!-- You can see the use of malloc( ) to create storage for the object in the line: -->
      <para>
		Observe el uso de <function>malloc()</function> para la obtención de espacio para
		el objeto:
      </para>

      <programlisting>
	Obj* obj = (Obj*)malloc(sizeof(Obj));
      </programlisting>


      <!--
      Here, the user must determine the size of the object (one place for an error). malloc( )
      returns a void* because it just produces a patch of memory, not an object. C++ doesn’t
      allow a void* to be assigned to any other pointer, so it must be cast.
      -->
      <para>
		Se debe pasar como parámetro a <function>malloc()</function> el tamaño del
		objeto. El tipo de retorno de <function>malloc()</function> es <type>void*</type>,
		pues es sólo un puntero a un bloque de memoria, no un objeto. En C++ no se permite
		la asignación directa de un <type>void*</type> a ningún otro tipo de
		puntero, de ahí la necesidad de la conversión explícita de tipo (molde).
      </para>


      <!--
      Because malloc( ) may fail to find any memory (in which case it returns zero), you must
      check the returned pointer to make sure it was successful.
      -->
      <para>
		Puede ocurrir que <function>malloc()</function> no encuentre un bloque adecuado,
		en cuyo caso devolverá un puntero nulo, de ahí la necesidad de comprobar la
		validez del puntero devuelto.
      </para>

      <!-- But the worst problem is this line: -->

      <para>
		El principal escollo está en la línea:
      </para>

      <programlisting>
	obj->initialize();
      </programlisting>


      <!--
      If users make it this far correctly, they must remember to initialize the object before
      it is used. Notice that a constructor was not used because the constructor cannot be
      called explicitly[50] – it’s called for you by the compiler when an object is created.
      The problem here is that the user now has the option to forget to perform the
      initialization before the object is used, thus reintroducing a major source of bugs.
      -->

    <!--
    [50] There is a special syntax called placement new that allows you to call a
    constructor for a pre-allocated piece of memory. This is introduced later in the
    chapter.
    -->

      <para>
		El usuario deberá asegurarse de inicializar el objeto antes de su uso. Obsérvese
		que no se ha usado el constructor debido a que éste no puede ser llamado de modo
		explícito <footnote><para>Existe una sintaxis especial llamada
		<foreignphrase>placement-new</foreignphrase> que permite llamar al constructor
		para un bloque de memoria preasignando. Se verá más adelante, en este mismo
		capítulo.</para></footnote>; es llamado por el compilador cuando se crea un
		objeto.  El problema es que el usuario puede olvidar inicializar el objeto antes
		de usarlo, introduciendo así una importante fuente de problemas.
      </para>


      <!--
      It also turns out that many programmers seem to find C’s dynamic memory functions too
      confusing and complicated; it’s not uncommon to find C programmers who use virtual
      memory machines allocating huge arrays of variables in the static storage area to avoid
      thinking about dynamic memory allocation. Because C++ is attempting to make library use
      safe and effortless for the casual programmer, C’s approach to dynamic memory is
      unacceptable.
      -->
      <para>
		Como consecuencia, muchos programadores encuentran muy confusas y complicadas las
		funciones de asignación dinámica de la memoria en C. No es muy difícil encontrar
		programadores que, usando máquinas con memoria virtual, usan vectores enormes en
		el área de almacenamiento estático para evitar tener que tratar con la asignación
		dinámica. Dado que C++ intenta facilitar el uso de la biblioteca a los
		programadores ocasionales, no es aceptable la forma de abordar la asignación
		dinámica en C.
      </para>
    </sect2>

    <sect2>
      <!-- : operator new -->
      <title>El operador <kw>new</kw></title>

      <!--
      The solution in C++ is to combine all the actions necessary to create an object into
      a single operator called new. When you create an object with new (using a
      new-expression), it allocates enough storage on the heap to hold the object and
      calls the constructor for that storage. Thus, if you say
      -->
      <para>
	La solución que ofrece C++ consiste en combinar la serie de acciones necesarias
	para la creación de un objeto en un único operador llamado <kw>new</kw>. Cuando se
	crea un objeto mediante el operador <kw>new</kw>, éste se encarga de obtener el
	espacio necesario para el objeto y de llamar a su constructor. Cuando se ejecuta
	el código:
      </para>

      <programlisting>
	MyType *fp = new MyType(1,2);
      </programlisting>


      <!--
      at runtime, the equivalent of malloc(sizeof(MyType)) is called (often, it is
      literally a call to malloc( )), and the constructor for MyType is called with the
      resulting address as the this pointer, using (1,2) as the argument list. By the time
      the pointer is assigned to fp, it’s a live, initialized object – you can’t even get
      your hands on it before then. It’s also automatically the proper MyType type so no
      cast is necessary.
      -->

      <para>
	se asigna espacio mediante alguna llamada equivalente a
	<code>malloc(sizeof(MyType))</code> --con frecuencia es así, literalmente--, y
	usando la dirección obtenida como puntero <kw>this</kw>, y <code>(1, 2)</code>
	como argumentos, se llama al constructor de la clase
	<classname>MyType</classname>.  Para cuando está disponible, el valor de retorno
	de <kw>new</kw> es ya un puntero válido a un objeto inicializado. Además es del
	tipo correcto, lo que hace innecesaria la conversión.
      </para>


      <!--
      The default new checks to make sure the memory allocation was successful before passing
      the address to the constructor, so you don’t have to explicitly determine if the call
      was successful. Later in the chapter you’ll find out what happens if there’s no memory
      left.
      -->
      <para>
		El operador <kw>new</kw> por defecto, comprueba el éxito o fracaso de la
		asignación de memoria como paso previo a la llamada al constructor, haciendo
		innecesaria y redundante la posterior comprobación.  Más adelante en este capítulo
		se verá qué sucede si se produce este fallo.
      </para>


      <!--
      You can create a new-expression using any constructor available for the class. If the
      constructor has no arguments, you write the new-expression without the constructor
      argument list:
      -->
      <para>
		En las expresiones con <kw>new</kw> se puede usar cualquiera de los constructores
		disponibles para una clase. Si éste no tiene argumentos, se escribe la expresión
		sin lista de argumentos
      </para>

      <programlisting>
	MyType *fp = new MyType;
      </programlisting>


      <!--
      Notice how simple the process of creating objects on the heap becomes – a single
      expression, with all the sizing, conversions, and safety checks built in. It’s as easy
      to create an object on the heap as it is on the stack.
      -->
      <para>
		Es notable la simpleza alcanzada en la creación dinámica de objetos: una única
		expresión realiza todo el trabajo de cálculo de tamaño, asignación, comprobaciones
		de seguridad y conversión de tipo. Esto hace que la creación dinámica de objetos
		sea tan sencilla como la creación en la pila.
      </para>

    </sect2>

    <sect2>
      <!-- : operator delete -->
      <title>El operador <kw>delete</kw></title>

      <!--
      The complement to the new-expression is the delete-expression, which first calls the
      destructor and then releases the memory (often with a call to free( )). Just as a
      new-expression returns a pointer to the object, a delete-expression requires the address
      of an object.
      -->
      <para>
		El complemento a la expresión <kw>new</kw> es la expresión <kw>delete</kw>, que
		primero llama al destructor y después libera la memoria (a menudo mediante una
		llamada a <function>free()</function>). El argumento para una expresión con
		<kw>delete</kw> debe ser una dirección: un puntero a objeto creado mediante
		<kw>new</kw>.
      </para>


      <programlisting>
	delete fp;
      </programlisting>


      <!--
      This destructs and then releases the storage for the dynamically allocated MyType object
      created earlier.
      -->
      <para>
		Esta expresión destruye el objeto y después libera el espacio dinámicamente
		asignado al objeto <type>MyType</type>
      </para>


      <!--
      delete can be called only for an object created by new. If you malloc( ) (or calloc( )
      or realloc( )) an object and then delete it, the behavior is undefined. Because most
      default implementations of new and delete use malloc( ) and free( ), you’d probably end
      up releasing the memory without calling the destructor.
      -->
      <para>
		El uso del operador <kw>delete</kw> debe limitarse a los objetos que hayan sido
		creados mediante <kw>new</kw>. Las consecuencias de aplicar el operador
		<kw>delete</kw> a los objetos creados con <function>malloc()</function>,
		<function>calloc()</function> o <function>realloc()</function> no están
		definidas. Dado que la mayoría de las implementaciones por defecto de <kw>new</kw>
		y <kw>delete</kw> usan <function>malloc()</function> y
		<function>free()</function>, el resultado será probablemente la liberación de la
		memoria sin la llamada al destructor.
      </para>

      <!--
      If the pointer you’re deleting is zero, nothing will happen. For this reason, people
      often recommend setting a pointer to zero immediately after you delete it, to prevent
      deleting it twice. Deleting an object more than once is definitely a bad thing to do,
      and will cause problems.
      -->
      <para>
		No ocurre nada si el puntero que se le pasa a <kw>delete</kw> es nulo. Por esa
		razón, a menudo se recomienda asignar cero al puntero inmediatamente después de
		usar <kw>delete</kw>; se evita así que pueda ser usado de nuevo como argumento
		para <kw>delete</kw>. Tratar de destruir un objeto más de una vez es un error de
		consecuencias imprevisibles.
      </para>
    </sect2>

    <sect2>
      <!-- : A simple example -->
      <title>Un ejemplo sencillo</title>

      <!-- This example shows that initialization takes place: -->
      <para>
		El siguiente ejemplo demuestra que la inicialización tiene lugar:
      </para>


//: V1C13:Tree.h



	  <!-- We can prove that the constructor is called by printing out the value of the
	  Tree. Here, it's done by overloading the operator << to use with an ostream and a
	  Tree*. Note, however, that even though the function is declared as a friend, it is
	  defined as an inline! This is a mere convenience \u2013 defining a friend function
	  as an inline to a class doesn\u2019t change the friend status or the fact that
	  it's a global function and not a class member function. Also notice that the
	  return value is the result of the entire output expression, which is an ostream&amp;
	  (which it must be, to satisfy the return value type of the function) -->
      <para>
		Se puede probar que el constructor es invocado imprimiendo el valor de
		<classname>Tree</classname>. Aquí se hace sobrecargando el <function>operator
		&lt;&lt;</function> para usarlo con un <varname>ostream</varname> y un
		<type>Tree*</type>. Note, sin embargo, que aunque la función está declarada como
		<kw>friend</kw>, está definida como una <kw>inline</kw>!. Esto es así por
		conveniencia --definir una función amiga como <kw>inline</kw> a una clase no
		cambia su condición de amiga o el hecho de que es una función global y no un
		método. También resaltar que el valor de retorno es el resultado de una expresión
		completa (el <type>ostream&amp;</type>), y así debe ser, para satisfacer el
		tipo del valor de retorno de la función.
      </para>
    </sect2>


	<sect2>
      <!-- : Memory manager overhead -->
      <title>Trabajo extra para el gestor de memoria</title>

      <!--
      When you create automatic objects on the stack, the size of the objects and their
      lifetime is built right into the generated code, because the compiler knows the exact
      type, quantity, and scope. Creating objects on the heap involves additional overhead,
      both in time and in space. Here’s a typical scenario. (You can replace malloc( ) with
      calloc( ) or realloc( ).)
	  <para>
      -->
	  <para>
		Cuando se crean objetos automáticos en la pila, el tamaño de los objetos y su
		tiempo de vida queda fijado en el código generado, porque el compilador conoce su
		tipo, cantidad y alcance. Crear objetos en el montículo implica una sobrecarga
		adicional, tanto en tiempo como en espacio. Veamos el escenario típico (Puede
		reemplazar <function>malloc()</function> con <function>calloc()</function> o
		<function>realloc()</function>).
	  </para>

	  <!--
	  You call malloc( ), which requests a block of memory from the pool. (This code
      may actually be part of malloc( ).)
	  -->
	  <para>
		Se invoca <function>malloc()</function>, que pide un bloque de memoria. (Este
		código realmente puede ser parte de <function>malloc()</function>).
	  </para>


	  <!--
	  The pool is searched for a block of memory large enough to satisfy the request. This is
	  done by checking a map or directory of some sort that shows which blocks are
	  currently in use and which are available. It’s a quick process, but it may take
	  several tries so it might not be deterministic – that is, you can’t necessarily
	  count on malloc( ) always taking exactly the same amount of time.
	  -->
      <para>
		Ahora tiene lugar la búsqueda de un bloque de tamaño adecuado de entre los bloques
		libres. Esto requiere la comprobación de un mapa o directorio de algún tipo que
		lleve el registro de los bloques disponibles y de los que están en uso. Es un
		proceso rápido, pero puede que necesite varias pruebas, es pues un proceso no
		determinista. Dicho de otro modo, no se puede contar con que
		<function>malloc()</function> tarde siempre exactamente el mismo tiempo en cada
		búsqueda.
      </para>

      <!--
      Before a pointer to that block is returned, the size and location of the block must be
      recorded so further calls to malloc( ) won’t use it, and so that when you call free( ),
      the system knows how much memory to release.
      -->
      <para>
		Antes de entregar el puntero del bloque obtenido, hay que registrar en alguna
		parte su tamaño y localización para que <function>malloc()</function> no lo vuelva
		a usar y para que cuando se produzca la llamada a <function>free()</function>, el
		sistema sepa cuánto espacio ha de liberar.
      </para>

      <!--
      The way all this is implemented can vary widely. For example, there’s nothing to prevent
      primitives for memory allocation being implemented in the processor. If you’re curious,
      you can write test programs to try to guess the way your malloc( ) is implemented. You
      can also read the library source code, if you have it (the GNU C sources are always
      available).
      -->
      <para>
		El modo en que se implementan todas estas operaciones puede variar mucho. No hay
		nada que impida que puedan implementarse las primitivas de asignación de memoria
		en el conjunto de instrucciones del procesador. Si es suficientemente curioso,
		pueden escribir programas que permitan averiguar cómo está implementada
		<function>malloc()</function>. Si dispone de él, puede leer el código fuente de la
		biblioteca de funciones de C, si no, siempre está disponible el de GNU C.
      </para>
    </sect2>
  </sect1>


  <sect1>
    <!-- : Early examples redesigned -->
    <title>Rediseño de los ejemplos anteriores</title>

    <!--
    Using new and delete, the Stash example introduced previously in this book can be
    rewritten using all the features discussed in the book so far. Examining the new code
    will also give you a useful review of the topics.
    -->
    <para>
	  Puede reescribirse el ejemplo <classname>Stash</classname> que vimos anteriormente
	  en el libro, haciendo uso de los operadores <kw>new</kw> y <kw>delete</kw>, con las
	  características que se han visto desde entonces. A la vista del nuevo código se
	  pueden repasar estas cuestiones.
    </para>

    <!--
    At this point in the book, neither the Stash nor Stack classes will “own” the objects
    they point to; that is, when the Stash or Stack object goes out of scope, it will not
    call delete for all the objects it points to. The reason this is not possible is
    because, in an attempt to be generic, they hold void pointers. If you delete a void
    pointer, the only thing that happens is the memory gets released, because there’s no
    type information and no way for the compiler to know what destructor to call.
    -->
    <para>
	  Hasta este punto del libro, ninguna de las clases <classname>Stash</classname> ni
	  <classname>Stack</classname> poseerán los objetos a los que apuntan; es decir,
	  cuando el objeto <classname>Stash</classname> o <classname>Stack</classname> sale de
	  ámbito, no se invoca <kw>delete</kw> para cada uno de los objetos a los que
	  apunta. La razón por la que eso no es posible es porque, en un intento de conseguir
	  más generalidad, utilizan punteros <type>void</type>. Usar <kw>delete</kw> con
	  punteros <literal>void</literal> libera el bloque de memoria pero, al no existir
	  información de tipo, el compilador no sabe qué destructor debe invocar.
    </para>

    <sect2>
      <!-- : delete void* is probably a bug -->
	  <title><kw>delete</kw> <type>void*</type> probablemente es un error</title>

      <!--
      It’s worth making a point that if you call delete for a void*, it’s almost certainly
      going to be a bug in your program unless the destination of that pointer is very simple;
      in particular, it should not have a destructor. Here’s an example to show you what
      happens:
      -->
      <para>
		Es necesario puntualizar que, llamar a <kw>delete</kw> con un argumento
		<type>void*</type> es casi con seguridad un error en el programa, a no ser que el
		puntero apunte a un objeto muy simple; en particular, que no tenga un destructor.
		He aquí un ejemplo ilustrativo:
      </para>


//: V1C13:BadVoidPointerDeletion.cpp


      <!--
      The class Object contains a void* that is initialized to “raw” data (it doesn’t point to
      objects that have destructors). In the Object destructor, delete is called for this
      void* with no ill effects, since the only thing we need to happen is for the storage to
      be released.
      -->
      <para>
		La clase <classname>Object</classname> contiene la variable
		<varname>data</varname> de tipo <type>void*</type> que es inicializada para
		apuntar a un objeto simple que no tiene destructor. En el destructor de
		<classname>Object</classname> se llama a <kw>delete</kw> con este puntero, sin que
		tenga consecuencias negativas puesto que lo único que se necesita aquí es liberar
		la memoria.
      </para>

      <!--
      However, in main( ) you can see that it’s very necessary that delete know what type of
      object it’s working with. Here’s the output:
      -->
      <para>
		Ahora bien, se puede ver en <function>main()</function> la necesidad de que
		<kw>delete</kw> conozca el tipo del objeto al que apunta su argumento. Esta es la
		salida del programa:
      </para>

<screen>
Construyendo objeto a, tamaño = 40
Destruyendo objeto a
Construyendo objeto b, tamaño = 40
</screen>


      <!--
      Because delete a knows that a points to an Object, the destructor is called and thus the
      storage allocated for data is released. However, if you manipulate an object through a
      void* as in the case of delete b, the only thing that happens is that the storage for
      the Object is released – but the destructor is not called so there is no release of the
      memory that data points to. When this program compiles, you probably won’t see any
      warning messages; the compiler assumes you know what you’re doing. So you get a very
      quiet memory leak.
      -->
      <para>
		Como <kw>delete</kw> sabe que <varname>a</varname> es un puntero a
		<classname>Object</classname>, se lleva a cabo la llamada al destructor de
		<classname>Object</classname>, con lo que se libera el espacio asignado a
		<varname>data</varname>. En cambio, cuando se manipula un objeto usando un
		<type>void*</type>, como es el caso en <code>delete b</code>, se libera el bloque
		de <classname>Object</classname>, pero no se efectúa la llamada a su destructor,
		con lo que tampoco se liberará el espacio asignado a <varname>data</varname>,
		miembro de <classname>Object</classname>. Probablemente no se mostrará ningún
		mensaje de advertencia al compilar el programa; no hay ningún error
		sintáctico. Como resultado obtenemos un programa con una silenciosa fuga de
		memoria.
      </para>

      <!--
      If you have a memory leak in your program, search through all the delete statements and
      check the type of pointer being deleted. If it’s a void* then you’ve probably found one
      source of your memory leak (C++ provides ample other opportunities for memory leaks,
      however).
      -->
      <para>
		Cuando se tiene una fuga de memoria, se debe buscar entre todas las llamadas a
		<kw>delete</kw> para comprobar el tipo de puntero que se le pasa. Si es un
		<type>void*</type>, puede estar ante una de las posibles causas (Sin embargo, C++
		proporciona otras muchas oportunidades para la fuga de memoria).
      </para>
    </sect2>

    <sect2>
      <!-- : Cleanup responsibility with pointers -->

      <title>Responsabilidad de la limpieza cuando se usan punteros</title>

      <!--
      To make the Stash and Stack containers flexible (able to hold any type of object), they
      will hold void pointers. This means that when a pointer is returned from the Stash or
      Stack object, you must cast it to the proper type before using it; as seen above, you
      must also cast it to the proper type before deleting it or you’ll get a memory leak.
      -->
      <para>
		Para hacer que los contenedores <classname>Stack</classname> y
		<classname>Stash</classname> sean flexibles, capaces de recibir cualquier tipo de
		objeto, se usan punteros de tipo <type>void*</type>. Esto hace necesario convertir
		al tipo adecuado los punteros devueltos por las clases
		<classname>Stash</classname> y <classname>Stack</classname>, antes de que sean
		usados. Hemos visto en la sección anterior, que los punteros deben ser convertidos
		al tipo correcto incluso antes de ser entregados a <kw>delete</kw>, para evitar
		posibles fugas de memoria.
      </para>

      <!--
      The other memory leak issue has to do with making sure that delete is actually called
      for each object pointer held in the container. The container cannot “own” the pointer
      because it holds it as a void* and thus cannot perform the proper cleanup. The user must
      be responsible for cleaning up the objects. This produces a serious problem if you add
      pointers to objects created on the stack and objects created on the heap to the same
      container because a delete-expression is unsafe for a pointer that hasn’t been allocated
      on the heap. (And when you fetch a pointer back from the container, how will you know
      where its object has been allocated?) Thus, you must be sure that objects stored in the
      following versions of Stash and Stack are made only on the heap, either through careful
      programming or by creating classes that can only be built on the heap.
      -->
      <para>
		Hay otro problema, derivado de la necesidad de llamar a <kw>delete</kw> para cada
		puntero a objeto almacenado en el contenedor. El contenedor no puede realizar la
		limpieza para los punteros que almacena puesto que son punteros
		<type>void*</type>. Esto puede derivar en un serio problema si a un contenedor se
		le pasan punteros a objetos automáticos junto con punteros a objetos dinámicos; el
		resultado de usar <kw>delete</kw> sobre un puntero que no haya sido obtenido del
		montículo es imprevisible. Más aún, al obtener del contenedor un puntero
		cualquiera, existirán dudas sobre el origen, automático, dinámico o estático, del
		objeto al que apunta. Esto implica que hay que asegurarse del origen dinámico de
		los punteros que se almacenen en la siguiente versión de
		<classname>Stash</classname> y <classname>Stack</classname>, bien sea mediante una
		programación cuidadosa, o bien por la creación de clases que sólo puedan ser
		construidas en el montículo.
      </para>

      <!--
      It’s also important to make sure that the client programmer takes responsibility for
      cleaning up all the pointers in the container. You’ve seen in previous examples how the
      Stack class checks in its destructor that all the Link objects have been popped. For a
      Stash of pointers, however, another approach is needed.
      -->
      <para>
		Es muy importante asegurarse también de que el programador cliente se
		responsabilice de la limpieza de los punteros del contenedor. Se ha visto en
		ejemplos anteriores que la clase <classname>Stack</classname> comprobaba en su
		destructor que todos los objetos <classname>Link</classname> habían sido
		desapilados. Un objeto <classname>Stash</classname> para punteros requiere un modo
		diferente de abordar el problema.
      </para>

    </sect2>

    <sect2>
      <!-- : Stash for pointers -->
      <title>Stash para punteros</title>

      <!--
      This new version of the Stash class, called PStash, holds pointers to objects that exist
      by themselves on the heap, whereas the old Stash in earlier chapters copied the objects
      by value into the Stash container. Using new and delete, it’s easy and safe to hold
      pointers to objects that have been created on the heap.
      -->
      <para>
		Esta nueva versión de la clase <classname>Stash</classname>, que llamamos
		<classname>PStash</classname>, almacena punteros a objetos existentes en el
		montículo, a diferencia de la vieja versión, que guardaba una copia por valor de
		los objetos. Usando <kw>new</kw> y <kw>delete</kw>, es fácil y seguro almacenar
		punteros a objetos creados en el montículo.
      </para>

      <!-- Here’s the header file for the “pointer Stash”: -->
      <para>
		He aquí el archivo de cabecera para <quote><classname>Stash</classname> para
		punteros</quote>:
      </para>


//: V1C13:PStash.h


      <!--
      The underlying data elements are fairly similar, but now storage is an array of void
      pointers, and the allocation of storage for that array is performed with new instead of
      malloc( ). In the expression
      -->
      <para>
		Los elementos de datos subyacentes no han cambiado mucho, pero ahora el
		almacenamiento se hace sobre un vector de punteros <type>void</type>, que se
		obtiene mediante <kw>new</kw> en lugar de <function>malloc()</function>.  En la
		expresión
      </para>

      <programlisting>
	void** st = new void*[ quantity + increase ];
      </programlisting>

      <!--
      the type of object allocated is a void*, so the expression allocates an array of void
      pointers.
      -->
      <para>
		se asigna espacio para un vector de punteros a <type>void</type>.
      </para>

      <!--
      The destructor deletes the storage where the void pointers are held rather than
      attempting to delete what they point at (which, as previously noted, will release their
      storage and not call the destructors because a void pointer has no type information).
      -->
      <para>
		El destructor de la clase libera el espacio en el que se almacenan los punteros
		sin tratar de borrar los objetos a los que hacen referencia, ya que esto,
		insistimos, liberaría el espacio asignado a los objetos, pero no se produciría la
		necesaria llamada a sus destructores por la falta de información de tipo.
      </para>

      <!--
      The other change is the replacement of the fetch( ) function with operator[ ], which
      makes more sense syntactically. Again, however, a void* is returned, so the user must
      remember what types are stored in the container and cast the pointers when fetching them
      out (a problem that will be repaired in future chapters).
      -->
      <para>
		El otro cambio realizado es el reemplazo de la función
		<function>fetch()</function> por <function>operator []</function>, más
		significativo sintácticamente. Su tipo de retorno es nuevamente
		<type>void*</type>, por lo que el usuario deberá recordar el tipo de los objetos a
		que se refieren y efectuar la adecuada conversión al extraerlos del
		contenedor. Resolveremos este problema en capítulos posteriores.
      </para>

      <!-- Here are the member function definitions: -->
      <para>Sigue la definición de los métodos de <classname>PStash</classname>:</para>


//: V1C13:PStash.cpp


      <!--
      The add( ) function is effectively the same as before, except that a pointer is stored
      instead of a copy of the whole object.
      -->
      <para>
		La función <function>add()</function> es, en efecto, la misma que antes si
		exceptuamos el hecho de que lo que se almacena ahora es un puntero a un objeto en
		lugar de una copia del objeto.
      </para>

      <!--
      The inflate( ) code is modified to handle the allocation of an array of void* instead of
      the previous design, which was only working with raw bytes. Here, instead of using the
      prior approach of copying by array indexing, the Standard C library function memset( )
      is first used to set all the new memory to zero (this is not strictly necessary, since
      the PStash is presumably managing all the memory correctly – but it usually doesn’t hurt
      to throw in a bit of extra care). Then memcpy( ) moves the existing data from the old
      location to the new. Often, functions like memset( ) and memcpy( ) have been optimized
      over time, so they may be faster than the loops shown previously. But with a function
      like inflate( ) that will probably not be used that often you may not see a performance
      difference. However, the fact that the function calls are more concise than the loops
      may help prevent coding errors.
      -->
      <para>
		El código de <function>inflate()</function> ha sido modificado para gestionar la
		asignación de memoria para un vector de <type>void*</type>, a diferencia del
		diseño previo, que sólo trataba con bytes. Aquí, en lugar de usar el método de
		copia por el índice del vector, se pone primero a cero el vector usando la función
		<function>memset()</function> de la biblioteca estándar de C, aunque esto no sea
		estrictamente necesario ya que, presumiblemente, <classname>PStash</classname>
		manipulará la memoria de forma adecuada, pero a veces no es muy costoso añadir un
		poco más de seguridad. A continuación, se copian al nuevo vector usando
		<function>memcpy()</function> los datos existentes en el antiguo. Con frecuencia
		verá que las funciones <function>memcpy()</function> y
		<function>memset()</function> han sido optimizadas en cuanto al tiempo de proceso,
		de modo que pueden ser más rápidas que los bucles anteriormente vistos. No
		obstante, una función como <function>inflate()</function> no es probable que sea
		llamada con la frecuencia necesaria para que la diferencia sea palpable. En
		cualquier caso, el hecho de que las llamadas a función sean más concisas que los
		bucles, puede ayudar a prevenir errores de programación.
      </para>

      <!--
      To put the responsibility of object cleanup squarely on the shoulders of the client
      programmer, there are two ways to access the pointers in the PStash: the operator[],
      which simply returns the pointer but leaves it as a member of the container, and a
      second member function remove( ), which returns the pointer but also removes it from the
      container by assigning that position to zero. When the destructor for PStash is called,
      it checks to make sure that all object pointers have been removed; if not, you’re
      notified so you can prevent a memory leak (more elegant solutions will be forthcoming in
      later chapters).
      -->
      <para>
		Para dejar definitivamente la responsabilidad de la limpieza de los objetos sobre
		los hombros del programador cliente, se proporcionan dos formas de acceder a los
		punteros en <classname>PStash</classname>: el operador <oper>[]</oper>, que
		devuelve el puntero sin eliminarlo del contenedor, y un segundo método
		<function>remove()</function> que además de devolver el puntero lo elimina del
		contenedor, poniendo a cero la posición que ocupaba. Cuando se produce la llamada
		al destructor de <classname>PStash</classname>, se prueba si han sido previamente
		retirados todos los punteros, si no es así, se notifica, de modo que es posible
		prevenir la fuga de memoria. Se verán otras soluciones mas elegantes en capítulos
		posteriores.
      </para>

      <sect3>
        <!-- : A test -->
		<title>Una prueba</title>

        <!-- Here’s the old test program for Stash rewritten for the PStash: -->
		<para>
		  Aquí aparece el programa de prueba de <classname>Stash</classname>, reescrito
		  para <classname>PStash</classname>:
		</para>


//: V1C13:PStashTest.cpp


        <!--
        As before, Stashes are created and filled with information, but this time the
        information is the pointers resulting from new-expressions. In the first case, note the
        line:
        -->
		<para>
		  Igual que antes, se crean y rellenan varias <classname>Stash</classname>, pero
		  esta vez con los punteros obtenidos con <kw>new</kw>. En el primer caso, véase
		  la línea:
		</para>

		<programlisting>
		  intStash.add(new int(i));
		</programlisting>

        <!--
        The expression new int(i) uses the pseudo-constructor form, so storage for a new int
        object is created on the heap, and the int is initialized to the value i.
        -->
		<para>
		  Se ha usado una forma de pseudo constructor en la expresión <code>new
		  int(i)</code>, con lo que además de crear un objeto <type>int</type> en el área
		  de memoria dinámica, le asigna el valor inicial <varname>i</varname>.
		</para>


        <!--
        During printing, the value returned by PStash::operator[ ] must be cast to the proper
        type; this is repeated for the rest of the PStash objects in the program. It’s an
        undesirable effect of using void pointers as the underlying representation and will be
        fixed in later chapters.
        -->
		<para>
		  Para imprimir, es necesario convertir al tipo adecuado el puntero obtenido de
		  <function>PStash::operator[]</function>; lo mismo se repite con el resto de los
		  objetos de <classname>PStatsh</classname> del programa. Es la consecuencia
		  indeseable del uso de punteros <type>void</type> como representación subyacente,
		  que se corregirá en capítulos posteriores.
		</para>



        <!--
        The second test opens the source code file and reads it one line at a time into another
        PStash. Each line is read into a string using getline( ), then a new string is created
        from line to make an independent copy of that line. If we just passed in the address of
        line each time, we’d get a whole bunch of pointers pointing to line, which would only
        contain the last line that was read from the file.
        -->
		<para>
		  En la segunda prueba, se lee línea a línea el propio archivo fuente. Mediante
		  <function>getline()</function> se lee cada línea de texto en una variable de
		  <type>cadena</type>, de la que se crea una copia independiente. Si le hubiéramos
		  pasado cada vez la dirección de <varname>line</varname>, tendríamos un montón de
		  copias del mismo puntero, referidas a la última línea leída.
		</para>

        <!-- When fetching the pointers, you see the expression: -->
		<para>
		  En, en la recuperación de los punteros, verá la expresión:
		</para>

		<programlisting>
		  *(string*)stringStash[v];
		</programlisting>

        <!--
        The pointer returned from operator[ ] must be cast to a string* to give it the proper
        type. Then the string* is dereferenced so the expression evaluates to an object, at
        which point the compiler sees a string object to send to cout.
        -->
		<para>
		  El puntero obtenido por medio de <function>operator[]</function> debe ser
		  convertido a <type>string*</type> para tener el tipo adecuado. Después el
		  <type>string*</type> es de-referenciado y es visto por el compilador como un
		  objeto <type>string</type> que se envía a <varname>cout</varname>.
		</para>

        <!--
        The objects created on the heap must be destroyed through the use of the remove( )
        statement or else you’ll get a message at runtime telling you that you haven’t
        completely cleaned up the objects in the PStash. Notice that in the case of the int
        pointers, no cast is necessary because there’s no destructor for an int and all we need
        is memory release:
        -->
		<para>
		  Antes de destruir los objetos, se han de eliminar las referencias
		  correspondientes mediante el uso de <function>remove()</function>. De no hacerse
		  así, <classname>PStash</classname> notificará que no se ha efectuado la limpieza
		  correctamente.  Véase que en el caso de los punteros a <type>int</type>, no es
		  necesaria la conversión de tipo al carecer de destructor, y lo único que se
		  necesita es liberar la memoria:
		</para>


	  <programlisting>
	    delete intStash.remove(k);
	  </programlisting>


        <!--
        However, for the string pointers, if you forget to do the cast you’ll have another
        (quiet) memory leak, so the cast is essential:
        -->
		<para>
		  En cambio, para los punteros a <type>string</type>, hace falta la conversión de
		  tipo, so pena de crear otra (silenciosa) fuga de memoria, de modo que el molde
		  es esencial:
		</para>


	  <programlisting>
	    delete (string*) stringStash.remove(k);
	  </programlisting>


        <!--
        Some of these issues (but not all) can be removed using templates (which you’ll learn
        about in Chapter 16).
        -->
		<para>
		  Algunas de estas dificultades pueden resolverse mediante el uso de plantillas,
		  que veremos en el capítulo 16. FIXME:ref
		</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <!-- 592 -->

    <!-- : new & delete for arrays -->
    <title>
      <kw>new</kw> y <kw>delete</kw> para vectores
    </title>

    <!--
    In C++, you can create arrays of objects on the stack or on the heap with equal ease,
    and (of course) the constructor is called for each object in the array. There’s one
    constraint, however: There must be a default constructor, except for aggregate
    initialization on the stack (see Chapter 6), because a constructor with no arguments
    must be called for every object.
    -->
    <para>
      En C++ es igual de fácil crear vectores de objetos en la pila o en el montículo, con
      la certeza de que se producirá la llamada al constructor para cada uno de los
      objetos del vector. Hay una restricción: debe existir un constructor por defecto, o
      sea, sin argumentos, que será invocado para cada objeto.
    </para>

    <!--
    When creating arrays of objects on the heap using new, there’s something else you must
    do. An example of such an array is
    -->
    <para>
      Cuando se crean vectores de objetos dinámicamente, usando <kw>new</kw>, hay otras
      cosas que hay que tener en cuenta. Como ejemplo de este tipo de vectores véase
    </para>

    <programlisting>
      MyType* fp = new MyType[100];
    </programlisting>

    <!--
    This allocates enough storage on the heap for 100 MyType objects and calls the
    constructor for each one. Now, however, you simply have a MyType*, which is exactly the
    same as you’d get if you said
    -->
    <para>
      Esta sentencia asigna espacio suficiente en el montículo para 100 objetos
      <classname>MyType</classname> y llama al constructor para cada uno de ellos. Lo que
      se ha obtenido es simplemente un <type>MyType*</type>, exactamente lo mismo que
      hubiera obtenido de esta otra forma, que crea un único objeto:
    </para>

    <programlisting>
      MyType* fp2 = new MyType;
    </programlisting>

    <!--
    to create a single object. Because you wrote the code, you know that fp is actually the
    starting address of an array, so it makes sense to select array elements using an
    expression like fp[3]. But what happens when you destroy the array? The statements
    -->
    <para>
      El escritor del programa sabe que <varname>fp</varname> es la dirección del primer
      elemento de un vector, por lo que tiene sentido seleccionar elementos del mismo
      mediante una expresión como <code>fp[3]</code>, pero ¿qué pasa cuando
      destruimos el vector?. Las sentencias
    </para>

      <programlisting>
	delete fp2;  // Correcta
	delete fp;   // Ésta no tendrá el efecto deseado
      </programlisting>

    <!--
    look exactly the same, and their effect will be the same. The destructor will be called
    for the MyType object pointed to by the given address, and then the storage will be
    released. For fp2 this is fine, but for fp this means that the other 99 destructor calls
    won’t be made. The proper amount of storage will still be released, however, because it
    is allocated in one big chunk, and the size of the whole chunk is stashed somewhere by
    the allocation routine.
    -->
    <para>
      parecen iguales, y sus efectos serán los mismos. Se llamará al destructor del objeto
      <classname>MyType</classname> al que apunta el puntero dado y después se liberará el
      bloque asignado. Esto es correcto para <varname>fp2</varname>, pero no lo es para
      <varname>fp</varname>, significa que los destructores de los 99 elementos restantes
      del vector no se invocarán. Sin embargo, sí se liberará toda la memoria asignada al
      vector, ya que fue obtenida como un único gran bloque cuyo tamaño quedó anotado en
      alguna parte por las rutinas de asignación.
    </para>

    <!--
    The solution requires you to give the compiler the information that this is actually the
    starting address of an array. This is accomplished with the following syntax:
    -->
    <para>
      Esto se soluciona indicando al compilador que el puntero que pasamos es la dirección
      de inicio de un vector, usando la siguiente sintaxis:
    </para>

    <programlisting>
      delete [] fp;
    </programlisting>

    <!--
    The empty brackets tell the compiler to generate code that fetches the number of objects
    in the array, stored somewhere when the array is created, and calls the destructor for
    that many array objects. This is actually an improved syntax from the earlier form,
    which you may still occasionally see in old code:
    -->
    <para>
      Los corchetes indican al compilador la necesidad de generar el código para obtener
      el número de objetos en el vector, que fue guardado en alguna parte cuando se creó,
      y llamar al destructor para cada uno de dichos elementos. Esta es una mejora sobre
      la sintaxis primitiva, que puede verse ocasionalmente en el código de viejos
      programas:
    </para>

    <programlisting>
      delete [100] fp;
    </programlisting>

    <!--
    which forced the programmer to include the number of objects in the array and introduced
    the possibility that the programmer would get it wrong. The additional overhead of
    letting the compiler handle it was very low, and it was considered better to specify the
    number of objects in one place instead of two.
    -->
    <para>
      que forzaba al programador a incluir el número de objetos contenidos en el vector,
      introduciendo con ello una posible fuente de errores. El esfuerzo adicional que
      supone para el compilador tener en esto en cuenta es pequeño, y por eso se consideró
      preferible especificar el número de objetos en un lugar y no en dos.
    </para>

    <sect2>
      <!-- : Making a pointer more like an array -->
      <title>Cómo hacer que un puntero sea más parecido a un vector</title>

	  <!--
	As an aside, the fp defined above can be changed to point to
	anything, which doesn\u2019t make sense for the starting address of an
	array. It makes more sense to define it as a constant, so any attempt
	to modify the pointer will be flagged as an error. To get this effect,
	you might try
	  -->
      <para>
		Como defecto colateral, existe la posibilidad de modificar el puntero
		<varname>fp</varname> anteriormente definido, para que apunte a cualquier otra
		cosa, lo que no es consistente con el hecho de ser la dirección de inicio de un
		vector. Tiene más sentido definirlo como una constante, de modo que cualquier
		intento de modificación sea señalado como un error. Para conseguir este efecto se
		podría probar con:
      </para>

      <programlisting>
	int const* q = new int[10];
      </programlisting>

      <para>
	o bien:
      </para>

      <programlisting>
	const int* q = new int[10];
      </programlisting>

      <!--
      but in both cases the const will bind to the int, that is, what is being pointed to,
      rather than the quality of the pointer itself. Instead, you must say
      -->
      <para>
		pero en ambos casos el especificador <kw>const</kw> quedaría asociado al
		<type>int</type>, es decir, al valor al que apunta, en lugar de al puntero en
		sí. Si se quiere conseguir el efecto deseado, en lugar de las anteriores, se debe
		poner:
      </para>

      <programlisting>
	int* const q = new int[10];
      </programlisting>

      <!--
      Now the array elements in q can be modified, but any change to q (like q++) is illegal,
      as it is with an ordinary array identifier.
      -->
      <para>
		Ahora es posible modificar el valor de los elementos del vector, siendo ilegal
		cualquier intento posterior de modificar <varname>q</varname>, como
		<literal>q++</literal> por ejemplo, al igual que ocurre con el identificador de un
		vector ordinario.
	  </para>
    </sect2>

    <sect2>
	  <!-- : Running out of storage -->
      <title>Cuando se supera el espacio de almacenamiento</title>

	  <!--
		  What happens when the operator new( ) cannot find a contiguous block of storage large
		  enough to hold the desired object? A special function called the new-handler is called.
		  Or rather, a pointer to a function is checked, and if the pointer is nonzero, then the
		  function it points to is called.
	  -->
      <para>
		¿Qué ocurre cuando <kw>new()</kw> no puede encontrar un bloque contiguo
		suficientemente grande para alojar el objeto? En este caso se produce la llamada a
		una función especial: el manejador de errores de <kw>new</kw> o
		<emphasis>new-handler</emphasis>. Para ello comprueba si un determinado puntero a
		función es nulo, si no lo es, se efectúa la llamada a la función a la que apunta.
      </para>

	  <!--
	  The default behavior for the new-handler is to throw an exception, a subject covered in
	  Volume 2. However, if you’re using heap allocation in your program, it’s wise to at
	  least replace the new-handler with a message that says you’ve run out of memory and then
	  aborts the program. That way, during debugging, you’ll have a clue about what happened.
	  For the final program you’ll want to use more robust recovery.
	  -->
      <para>
		El comportamiento por defecto del manejador de errores de <kw>new</kw> es disparar
		una excepción, asunto del que se tratará en el Volumen 2. Si se piensa usar la
		asignación dinámica, conviene al menos reemplazar el manejador de errores de
		<kw>new</kw> por una función que advierta de la falta de memoria y fuerce la
		terminación del programa. De este modo, durante la depuración del programa, se
		podrá seguir la pista de lo sucedido. Para la versión final del programa, será
		mejor implementar una recuperación de errores más elaborada.
      </para>

	  <!--
	  You replace the new-handler by including new.h and then calling set_new_handler( ) with
	  the address of the function you want installed:
	  -->
      <para>
		La forma de reemplazar el manejador de <emphasis>new-handler</emphasis> por defecto
		consiste en incluir el archivo <filename>new.h</filename> y hacer una llamada a la
		función <function>set_new_handler()</function> con la dirección de la función que
		se desea instalar:
      </para>


//: V1C13:NewHandler.cpp


	  <!-- The new-handler function must take no arguments and have a void return
	  value. The while loop will keep allocating int objects (and throwing away their
	  return addresses) until the free store is exhausted. At the very next call to new,
	  no storage can be allocated, so the new-handler will be called.  -->
      <para>
		La función a instalar debe retornar <type>void</type> y no tomar argumentos. El
		bucle <kw>while</kw> seguirá pidiendo bloques de <type>int</type> hasta consumir
		la memoria libre disponible, sin hacer nada con ellos. Justo a la siguiente
		llamada a <kw>new</kw>, no habrá espacio para asignar y se producirá la llamada al
		<emphasis>manejador de <kw>new</kw></emphasis>.
      </para>

	  <!-- The behavior of the new-handler is tied to operator new( ), so if you overload
	  operator new( ) (covered in the next section) the new-handler will not be called by
	  default. If you still want the new-handler to be called you’ll have to write the
	  code to do so inside your overloaded operator new( ).  -->
      <para>
		Este comportamiento del <emphasis>new-handler</emphasis> está asociado al
		<function>operator new()</function>, de modo que si se sobrecarga
		<function>operator new()</function> (asunto que se trata en la siguiente sección),
		no se producirá la llamada al <emphasis>manejador de <kw>new</kw></emphasis>. Si
		se desea que se produzca dicha llamada será necesario que lo haga en el
		<function>operator new()</function> que substituya al original.
      </para>

	  <!--
	  Of course, you can write more sophisticated new-handlers, even one to try to reclaim
	  memory (commonly known as a garbage collector). This is not a job for the novice
	  programmer.
	  -->

      <para>
		Por supuesto, es posible escribir manejadores <kw>new</kw> más sofisticados,
		incluso alguno que intente reclamar los bloques asignados que no se usan
		(conocidos habitualmente como <emphasis>recolectores de basura</emphasis>). Pero
		este no es un trabajo adecuado para programadores noveles.
      </para>
    </sect2>

    <sect2>
	  <!-- : Overloading new & delete -->
      <title>Sobrecarga de los operadores <kw>new</kw> y <kw>delete</kw></title>

	  <!-- When you create a new-expression, two things occur. First, storage is allocated
	  using the operator new( ), then the constructor is called. In a delete-expression,
	  the destructor is called, then storage is deallocated using the operator delete(
	  ). The constructor and destructor calls are never under your control (otherwise you
	  might accidentally subvert them), but you can change the storage allocation
	  functions operator new( ) and operator delete( ).  -->
      <para>
		Cuando se ejecuta una <emphasis>expresión con <kw>new</kw></emphasis>, ocurren dos
		cosas. Primero se asigna la memoria al ejecutar el código del <function>operator
		new()</function> y después se realiza la llamada al constructor. En el caso de una
		<emphasis>expresión con <kw>delete</kw></emphasis>, se llama primero al destructor
		y después se libera la memoria con el operador <function>operator
		delete()</function>. Las llamadas al constructor y destructor no están bajo el
		control del programador, pero se <emphasis>pueden</emphasis> cambiar las funciones
		<function>opertator new()</function> y <function>operatator delete()</function>.
      </para>


    <!--
    The memory allocation system used by new and delete is designed for general-purpose use.
    In special situations, however, it doesn’t serve your needs. The most common reason to
    change the allocator is efficiency: You might be creating and destroying so many objects
    of a particular class that it has become a speed bottleneck. C++ allows you to overload
    new and delete to implement your own storage allocation scheme, so you can handle
    problems like this.
    -->
      <para>
		El sistema de asignación de memoria usado por <kw>new</kw> y <kw>delete</kw> es un
		sistema de propósito general. En situaciones especiales, puede que no funcione
		como se requiere. 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 <kw>new</kw> y <kw>delete</kw> para implementar un esquema
		particular más adecuado que permita manejar situaciones como ésta.
      </para>
    <!--
    Another issue is heap fragmentation. By allocating objects of different sizes it’s
    possible to break up the heap so that you effectively run out of storage. That is, the
    storage might be available, but because of fragmentation no piece is big enough to
    satisfy your needs. By creating your own allocator for a particular class, you can
    ensure this never happens.
    -->
      <para>
		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.
      </para>

    <!--
    In embedded and real-time systems, a program may have to run for a very long time with
    restricted resources. Such a system may also require that memory allocation always take
    the same amount of time, and there’s no allowance for heap exhaustion or fragmentation.
    A custom memory allocator is the solution; otherwise, programmers will avoid using new
    and delete altogether in such cases and miss out on a valuable C++ asset.
    -->
	<para>
	  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
	  <quote>personalizado</quote>; de otro modo, los programadores evitarían usar
	  <kw>new</kw> y <kw>delete</kw> es estos casos y desperdiciarían un recurso muy
	  valioso de C++.
	</para>

    <!--
    When you overload operator new( ) and operator delete( ), it’s important to remember
    that you’re changing only the way raw storage is allocated. The compiler will simply
    call your new instead of the default version to allocate storage, then call the
    constructor for that storage. So, although the compiler allocates storage and calls the
    constructor when it sees new, all you can change when you overload new is the storage
    allocation portion. (delete has a similar limitation.)
    -->
      <para>
		A la hora de sobrecargar <function>operator new()</function> y <function>operator
		delete()</function> 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 <kw>new</kw> 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 <kw>new</kw> en código para asignar el espacio
		y para llamar al constructor, todo lo que se puede cambiar al sobrecargar
		<kw>new</kw> es la parte correspondiente a la asignación. <kw>delete</kw> tiene
		una limitación similar.
      </para>

    <!--
    When you overload operator new( ), you also replace the behavior when it runs out of
    memory, so you must decide what to do in your operator new( ): return zero, write a loop
    to call the new-handler and retry allocation, or (typically) throw a bad_alloc exception
    (discussed in Volume 2, available at www.BruceEckel.com).
    -->
      <para>
		Cuando se sobrecarga <function>operator new()</function>, 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 <foreignphrase>new-handler</foreignphrase>, o lo que es
		más frecuente, disparar una excepción <emphasis>bad_alloc</emphasis> (tema que se
		trata en el Volumen 2).
      </para>

    <!--
    Overloading new and delete is like overloading any other operator. However, you have a
    choice of overloading the global allocator or using a different allocator for a
    particular class.
    -->
      <para>
		La sobrecarga de <kw>new</kw> y <kw>delete</kw> es como la de cualquier otro
		operador. Existe la posibilidad de elegir entre sobrecarga global y sobrecarga
		para una clase determinada.
      </para>

      <sect3>
      <!-- : Overloading global new & delete -->
	  <title>Sobrecarga global de <kw>new</kw> y <kw>delete</kw></title>

      <!--
      This is the drastic approach, when the global versions of new and delete are
      unsatisfactory for the whole system. If you overload the global versions, you make the
      defaults completely inaccessible – you can’t even call them from inside your
      redefinitions.
      -->
	  <para>
		Este es el modo más drástico de abordar el asunto, resulta útil cuando el
		comportamiento de <kw>new</kw> y <kw>delete</kw> 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.
	  </para>

      <!--
      The overloaded new must take an argument of size_t (the Standard C standard type for
      sizes). This argument is generated and passed to you by the compiler and is the size of
      the object you’re responsible for allocating. You must return a pointer either to an
      object of that size (or bigger, if you have some reason to do so), or to zero if you
      can’t find the memory (in which case the constructor is not called!). However, if you
      can’t find the memory, you should probably do something more informative than just
      returning zero, like calling the new-handler or throwing an exception, to signal that
      there’s a problem.
      -->
	  <para>
		El <kw>new</kw> sobrecargado debe tomar un argumento del tipo <type>size_t</type>
		(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 <quote>new-handler</quote> o disparar una excepción,
		para indicar que hubo un problema.
	  </para>

      <!--
      The return value of operator new( ) is a void*, not a pointer to any particular type.
      All you’ve done is produce memory, not a finished object – that doesn’t happen until the
      constructor is called, an act the compiler guarantees and which is out of your control.
      -->
	  <para>
		El valor de retorno de <function>operator new()</function> es <type>void*</type>,
		no un puntero a un tipo particular. Lo que hace es obtener un bloque de memoria,
		no un objeto definido, no hasta que que sea llamado el constructor, un acto que el
		compilador garantiza y que está fuera del control de este operador.
	  </para>

      <!--
      The operator delete( ) takes a void* to memory that was allocated by operator new. It’s
      a void* because operator delete only gets the pointer after the destructor is called,
      which removes the object-ness from the piece of storage. The return type is void.
      -->
	  <para>
		El operador <function>operator delete()</function> toma como argumento un puntero
		<type>void*</type> a un bloque obtenido con el <function>operator
		new()</function>. Es un <type>void*</type> ya que el <kw>delete</kw> obtiene el
		puntero sólo <emphasis>después</emphasis> de que haya sido llamado el destructor,
		lo que efectivamente elimina su caracter de objeto convirtiéndolo en un simple
		bloque de memoria. El tipo de retorno para <kw>delete</kw> es <type>void</type>.
	  </para>

      <!-- Here’s a simple example showing how to overload the global new and delete: -->
	  <para>
		A continuación se expone un ejemplo del modo de sobrecargar globalmente
		<kw>new</kw> y <kw>delete</kw>:
	  </para>


//: V1C13:GlobalOperatorNew.cpp


      <!--
      Here you can see the general form for overloading new and delete. These use the Standard
      C library functions malloc( ) and free( ) for the allocators (which is probably what the
      default new and delete use as well!). However, they also print messages about what they
      are doing. Notice that printf( ) and puts( ) are used rather than iostreams. This is
      because when an iostream object is created (like the global cin, cout, and cerr), it
      calls new to allocate memory. With printf( ), you don’t get into a deadlock because it
      doesn’t call new to initialize itself.
      -->
	  <para>
	  Aquí puede verse la forma general de sobrecarga de operadores <kw>new</kw> y
	  <kw>delete</kw>.  Estos operadores sustitutivos usan las funciones
	  <function>malloc()</function> y <function>free()</function> de la biblioteca
	  estándar de C, que es probablemente lo que ocurre en los operadores
	  originales. Imprimen también mensajes sobre lo que están haciendo. Nótese que no se
	  han usado <literal>iostreams</literal> sino <function>printf()</function> y
	  <function>puts()</function>. Esto se hace debido a que los objetos
	  <type>iostream</type> como los globales <varname>cin</varname>,
	  <varname>cout</varname> y <varname>cerr</varname> llaman a <kw>new</kw> para obtener
	  memoria <footnote><para>Provocaría una serie continua de llamadas a <kw>new</kw>
	  hasta agotar la pila y abortaría el programa.</para></footnote>. Usar
	  <function>printf()</function> evita el fatal bloqueo, ya que no hace llamadas a
	  <kw>new</kw>.
	</para>

      <!--
      In main( ), objects of built-in types are created to prove that the overloaded new and
      delete are also called in that case. Then a single object of type S is created, followed
      by an array of S. For the array, you’ll see from the number of bytes requested that
      extra memory is allocated to store information (inside the array) about the number of
      objects it holds. In all cases, the global overloaded versions of new and delete are
      used.
      -->
	  <para>
		En <function>main()</function>, se crean algunos objetos de tipos básicos para
		demostrar que también en estos casos se llama a los operadores <kw>new</kw> y
		<kw>delete</kw> sobrecargados. Posteriormente, se crean un objeto simple y un
		vector, ambos de tipo <classname>S</classname>. En el caso del vector se puede
		ver, por el número de bytes pedidos, que se solicita algo de memoria extra para
		incluir información sobre el número de objetos que tendrá. En todos los casos se
		efectúa la llamada a las versiones globales sobrecargadas de <kw>new</kw> y
		<kw>delete</kw>.
	  </para>

	</sect3>


	<sect3>
      <!-- : Overloading new & delete for a class -->
	  <title>
		Sobrecarga de <kw>new</kw> y <kw>delete</kw> específica para una clase
	  </title>

      <!--
      Although you don’t have to explicitly say static, when you overload new and delete for a
      class, you’re creating static member functions. As before, the syntax is the same as
      overloading any other operator. When the compiler sees you use new to create an object
      of your class, it chooses the member operator new( ) over the global version. However,
      the global versions of new and delete are used for all other types of objects (unless
      they have their own new and delete).
      -->
	  <para>
		Aunque no es necesario poner el modificador <kw>static</kw>, cuando se sobrecarga
		<kw>new</kw> y <kw>delete</kw> para una clase se están creando métodos estáticos
		(métodos de clase). La sintaxis es la misma que para cualquier otro
		operador. Cuando el compilador encuentra una expresión <kw>new</kw> para crear un
		objeto de una clase, elige, si existe, un método de la clase llamado
		<function>operator new()</function> en lugar del <kw>new</kw> global. Para el
		resto de tipos o clases se usan los operadores globales (a menos que tengan
		definidos los suyos propios).
	  </para>


	  <!--
		  In the following example, a primitive storage allocation system is created for
		  the class Framis. A chunk of memory is set aside in the static data area at
		  program start-up, and that memory is used to allocate space for objects of type
		  Framis. To determine which blocks have been allocated, a simple array of bytes
		  is used, one byte for each block:
	  -->
	  <para>
		En el siguiente ejemplo se usa un primitivo sistema de asignación de
		almacenamiento para la clase <classname>Framis</classname>. Se reserva un bloque
		de memoria en el área de datos estática FIXME , y se usa esa memoria para asignar
		alojamiento para los objetos de tipo <classname>Framis</classname>. Para
		determinar qué bloques se han asignado, se usa un sencillo vector de bytes, un
		byte por bloque.
	  </para>


//: V1C13:Framis.cpp


      <!--
      The pool of memory for the Framis heap is created by allocating an array of bytes large
      enough to hold psize Framis objects. The allocation map is psize elements long, so
      there’s one bool for every block. All the values in the allocation map are initialized
      to false using the aggregate initialization trick of setting the first element so the
      compiler automatically initializes all the rest to their normal default value (which is
      false, in the case of bool).
      -->
	  <para>
		El espacio de almacenamiento para el montículo <classname>Framis</classname> se
		crea sobre el bloque obtenido al declarar un vector de tamaño suficiente para
		contener <varname>psize</varname> objetos de clase
		<classname>Framis</classname>. Se ha declarado también una variable lógica para
		cada uno de los <varname>psize</varname> bloques en el vector. Todas estas
		variables lógicas son inicializadas a <constant>false</constant> usando el truco
		consistente en inicializar el primer elemento para que el compilador lo haga
		automáticamente con los restantes iniciándolos a su valor por defecto,
		<constant>false</constant>, en el caso de variables lógicas.
	</para>

      <!--
      The local operator new( ) has the same syntax as the global one. All it does is search
      through the allocation map looking for a false value, then sets that location to true to
      indicate it’s been allocated and returns the address of the corresponding memory block.
      If it can’t find any memory, it issues a message to the trace file and throws a
      bad_alloc exception.
      -->
	  <para>
		El <function>operador new()</function> local usa la misma sintaxis que el
		global. Lo único que hace es buscar una posición libre, es decir, un valor
		<constant>false</constant> en el mapa de localización
		<varname>alloc_map</varname>. Si la encuentra, cambia su valor a
		<constant>true</constant> para marcarla como ocupada, y devuelve la dirección del
		bloque correspondiente. En caso de no encontrar ningún bloque libre, envía un
		mensaje al fichero de trazas y dispara una excepción de tipo
		<type>bad_alloc</type>.
	</para>

      <!--
      This is the first example of exceptions that you’ve seen in this book. Since detailed
      discussion of exceptions is delayed until Volume 2, this is a very simple use of them.
      In operator new( ) there are two artifacts of exception handling. First, the function
      argument list is followed by throw(bad_alloc), which tells the compiler and the reader
      that this function may throw an exception of type bad_alloc. Second, if there’s no more
      memory the function actually does throw the exception in the statement throw bad_alloc.
      When an exception is thrown, the function stops executing and control is passed to an
      exception handler, which is expressed as a catch clause.
      -->
	  <para>
		Este es el primer ejemplo con excepción que aparece en este libro.  En
		el Volumen 2 se verá una discusión detallada del tratamiento de
		excepciones, por lo que en este ejemplo se hace un uso muy simple del
		mismo. En el <function>operador new</function> hay dos expresiones
		relacionadas con el tratamiento de excepciones. Primero, a la lista de
		argumentos de función le sigue la expresión
		<code>throw(bad_alloc)</code>, esto informa al compilador que la
		función puede disparar una excepción del tipo indicado. En segundo
		lugar, si efectivamente se agota la memoria, la función alcanzará la
		sentencia <code>throw bad_alloc()</code> lanzando la excepción. En el
		caso de que esto ocurra, la función deja de ejecutarse y se cede el
		control del programa a la rutina de tratamiento de excepción que se ha
		definido en una cláusula <code>catch(bad_alloc)</code>.
     </para>

      <!--
      In main( ), you see the other part of the picture, which is the try-catch clause. The
      try block is surrounded by braces and contains all the code that may throw exceptions –
      in this case, any call to new that involves Framis objects. Immediately following the
      try block is one or more catch clauses, each one specifying the type of exception that
      they catch. In this case, catch(bad_alloc) says that that bad_alloc exceptions will be
      caught here. This particular catch clause is only executed when a bad_alloc exception is
      thrown, and execution continues after the end of the last catch clause in the group
      (there’s only one here, but there could be more).
      -->
		<para>
		  En <function>main()</function> se puede ver la cláusula
		  <emphasis>try-catch</emphasis> que es la otra parte del mecanismo. El
		  código que puede lanzar la excepción queda dentro del bloque
		  <kw>try</kw>; en este caso, llamadas a <kw>new</kw> para objetos
		  <classname>Framis</classname>. Justo a continuación de dicho bloque
		  sigue una o varias cláusulas <kw>catch</kw>, especificando en cada una
		  la excepción a la que se destina. En este caso,
		  <code>catch(bad_alloc)</code> indica que en ese bloque se
		  tratarán las excepciones de tipo <type>bad_alloc</type>.  El código de
		  este bloque sólo se ejecutará si se dispara la excepción, continuando
		  la ejecución del programa justo después de la última del grupo de
		  cláusulas <kw>catch</kw> que existan. Aquí sólo hay una, pero podría
		  haber más.
		</para>

      <!--
      In this example, it’s OK to use iostreams because the global operator new( ) and delete(
      ) are untouched.
      -->
		<para>
		  En este ejemplo, el uso de <literal>iostream</literal> es correcto ya
		  que el <function>operator new()</function> global no ha sido modificado.
		</para>

      <!--
      The operator delete( ) assumes the Framis address was created in the pool. This is a
      fair assumption, because the local operator new( ) will be called whenever you create a
      single Framis object on the heap – but not an array of them: global new is used for
      arrays. So the user might accidentally have called operator delete( ) without using the
      empty bracket syntax to indicate array destruction. This would cause a problem. Also,
      the user might be deleting a pointer to an object created on the stack. If you think
      these things could occur, you might want to add a line to make sure the address is
      within the pool and on a correct boundary (you may also begin to see the potential of
      overloaded new and delete for finding memory leaks).
      -->
		<para>
		  El <function>operator delete()</function> asume que la dirección de
		  <classname>Framis</classname> ha sido obtenida de nuestro almacén
		  particular. Una asunción justa, ya que cada vez que se crea un objeto
		  <classname>Framis</classname> simple se llama al <function>operator
		  new()</function> local; pero cuando se crea un vector de tales objetos
		  se llama al <kw>new</kw> global. Esto causaría problemas si el usuario
		  llamara accidentalmente al operador <kw>delete</kw> sin usar la
		  sintaxis para destrucción de vectores. Podría ser que incluso
		  estuviera tratando de borrar un puntero a un objeto de la pila. Si
		  cree que estas cosas puedan suceder, conviene pensar en añadir una
		  línea que asegurare que la dirección está en el intervalo correcto
		  (aquí se demuestra el potencial que tiene la sobrecarga de los
		  operadores <kw>new</kw> y <kw>delete</kw> para la localización de
		  fugas de memoria).
		</para>

      <!--
      operator delete( ) calculates the block in the pool that this pointer represents, and
      then sets the allocation map’s flag for that block to false to indicate the block has
      been released.
      -->
		<para>
		  <function>operador delete()</function> calcula el bloque al que el
		  puntero representa y después pone a <constant>false</constant> la
		  bandera correspondiente en el mapa de localización, para indicar que
		  dicho bloque está libre.
		</para>

      <!--
      In main( ), enough Framis objects are dynamically allocated to run out of memory; this
      checks the out-of-memory behavior. Then one of the objects is freed, and another one is
      created to show that the released memory is reused.
      -->
		<para>
		  En la función <function>main()</function>, se crean dinámicamente
		  suficientes objetos <classname>Framis</classname> para agotar la
		  memoria. Con esto se prueba el comportamiento del programa en este
		  caso. A continuación, se libera uno de los objetos y se crea otro para
		  mostrar la reutilización del bloque recién liberado.
		</para>


      <!--
      Because this allocation scheme is specific to Framis objects, it’s probably much faster
      than the general-purpose memory allocation scheme used for the default new and delete.
      However, you should note that it doesn’t automatically work if inheritance is used
      (inheritance is covered in Chapter 14).
      -->
		<para>
		  Este esquema específico de asignación de memoria es probablemente
		  mucho más rápido que el esquema de propósito general que usan los
		  operadores <kw>new</kw> y <kw>delete</kw> originales. Se debe
		  advertir, no obstante, que este enfoque no es automáticamente
		  utilizable cuando se usa herencia, un tema que verá en el Capítulo 14 (FIXME).
		</para>
      </sect3>


<!-- revisando por aquí -->

      <!-- 603 -->
      <sect3>
		<!-- : Overloading new & delete for arrays -->

		<title>Sobrecarga de <kw>new</kw> y <kw>delete</kw> para vectores</title>

      <!--
      If you overload operator new and delete for a class, those operators are called whenever
      you create an object of that class. However, if you create an array of those class
      objects, the global operator new( ) is called to allocate enough storage for the array
      all at once, and the global operator delete( ) is called to release that storage. You
      can control the allocation of arrays of objects by overloading the special array
      versions of operator new[ ] and operator delete[ ] for the class. Here’s an example that
      shows when the two different versions are called:
      -->
	<para>
	  Si se sobrecargan los operadores <kw>new</kw> y
	  <kw>delete</kw> para una clase, esos operadores se
	  llaman cada vez que se crea un objeto simple de esa clase. Sin
	  embargo, al crear un vector de tales objetos se llama al
	  <function>operator new()</function> global para obtener el
	  espacio necesario para el vector, y al <function>operator
	  delete()</function> global para liberarlo. Es posible
	  controlar también la asignación de memoria para vectores
	  sobrecargando los métodos <function>operator new[]</function>
	  y <function>operator delete[]</function>; se trata de
	  versiones especiales para vectores. A continuación se expone
	  un ejemplo que muestra el uso de ambas versiones.
	</para>


//: V1C13:ArrayOperatorNew.cpp

      <!--
      Here, the global versions of new and delete are called so the effect is the same as
      having no overloaded versions of new and delete except that trace information is added.
      Of course, you can use any memory allocation scheme you want in the overloaded new and
      delete.
      -->
	<para>
	  Si exceptuamos la información de rastreo que se añade aquí,
	  las llamadas a las versiones globales de
	  <kw>new</kw> y <kw>delete</kw> causan el
	  mismo efecto que si estos operadores no se hubieran
	  sobrecargado. Como se ha visto anteriormente, es posible usar
	  cualquier esquema conveniente de asignación de memoria en
	  estos operadores modificados.
	</para>

      <!--
      You can see that the syntax of array new and delete is the same as for the individual
      object versions except for the addition of the brackets. In both cases you’re handed the
      size of the memory you must allocate. The size handed to the array version will be the
      size of the entire array. It’s worth keeping in mind that the only thing the overloaded
      operator new( ) is required to do is hand back a pointer to a large enough memory block.
      Although you may perform initialization on that memory, normally that’s the job of the
      constructor that will automatically be called for your memory by the compiler.
      -->
	<para>
	  Se puede observar que la sintaxis de <kw>new</kw> y
	  <kw>delete</kw> para vectores es la misma que la
	  usada para objetos simples añadiéndoles el operador subíndice
	  <literal>[]</literal>. En ambos casos se le pasa a
	  <kw>new</kw> como argumento el tamaño del bloque de
	  memoria solicitado. A la versión para vectores se le pasa el
	  tamaño necesario para albergar todos sus componentes. Conviene
	  tener en cuenta que lo único que se requiere del
	  <function>operator new()</function> es que devuelva un puntero
	  a un bloque de memoria suficientemente grande. Aunque es
	  posible inicializar el bloque referido, eso es trabajo del
	  constructor, que se llamará automáticamente por el compilador.
	</para>

      <!--
      The constructor and destructor simply print out characters so you can see when they’ve
      been called. Here’s what the trace file looks like for one compiler:
      -->
	<para>
	  El constructor y el destructor simplemente imprimen
	  mensajes para que pueda verse que han sido llamados. A
	  continuación se muestran dichos mensajes:
	</para>

<screen>
new Widget
Widget::new: 40 bytes
*
delete Widget
~Widget::delete
new Widget[25]
Widget::new: 1004 bytes
*************************
delete []Widget
~~~~~~~~~~~~~~~~~~~~~~~~~Widget::delete[]
</screen>

      <!--
      Creating an individual object requires 40 bytes, as you might expect. (This machine uses
      four bytes for an int.) The operator new( ) is called, then the constructor (indicated
      by the *). In a complementary fashion, calling delete causes the destructor to be
      called, then the operator delete( ).
      -->
	<para>
	  La creación de un único objeto <classname>Widget</classname>
	  requiere 40 bytes, tal y como se podría esperar para una
	  máquina que usa 32 bits para un <type>int</type>. Se invoca al
	  <function>operator new()</function> y luego al constructor,
	  que se indica con la impresión del carácter
	  <quote>*</quote>. De forma complementaria, la llamada a
	  <kw>delete</kw> provoca primero la invocación del
	  destructor y sólo después, la de <literal>operator
	  delete()</literal>.
	</para>

      <!--
      When an array of Widget objects is created, the array version of operator new( ) is
      used, as promised. But notice that the size requested is four more bytes than expected.
      This extra four bytes is where the system keeps information about the array, in
      particular, the number of objects in the array. That way, when you say
      -->
	<para>
	  Cuando lo que se crea es un vector de objetos
	  <classname>Widget</classname>, se observa el uso de la versión
	  de <function>operator new()</function> para vectores, de acuerdo
	  con lo dicho anteriormente. Se observa que el tamaño del
	  bloque solicitado en este caso es cuatro bytes mayor que el
	  esperado. Es en estos cuatro bytes extra donde el compilador
	  guarda la información sobre el tamaño del vector. De ese
	  modo, la expresión
	</para>

	<programlisting>
	  delete []Widget;
	</programlisting>

      <!--
      the brackets tell the compiler it’s an array of objects, so the compiler generates code
      to look for the number of objects in the array and to call the destructor that many
      times. You can see that, even though the array operator new( ) and operator delete( )
      are only called once for the entire array chunk, the default constructor and destructor
      are called for each object in the array.
      -->
	<para>
	  informa al compilador que se trata de un vector, con lo cual,
	  generará el código para extraer la información que indica el
	  número de objetos y para llamar otras tantas veces al
	  destructor. Obsérvese que aunque se llame solo una vez a
	  <function>operator new()</function> y <function>operator
	  delete()</function> para el vector, se llama al constructor y
	  al destructor una vez para cada uno de los objetos del vector.
	</para>
      </sect3>


      <sect3>
      <!-- : Constructor calls -->
	<title>Llamadas al constructor</title>

      <!-- Considering that -->
	<para>
	  Considerando que
	</para>

	<programlisting>
	  MyType* f = new MyType;
	</programlisting>

<!--
 calls new to allocate a MyType-sized piece of storage, then invokes
 the MyType constructor on that storage, what happens if the storage
 allocation in new fails? The constructor is not called in that case, so
 although you still have an unsuccessfully created object, at least you
 haven\u2019t invoked the constructor and handed it a zero this
 pointer. Here\u2019s an example to prove it
-->
	<para>
	  llama a <kw>new</kw> para obtener un bloque del
	  tamaño de <classname>MyType</classname> invocando después a su
	  constructor, ¿qué pasaría si la asignación de memoria falla en
	  <kw>new</kw>?. En tal caso, no habrá llamada al
	  constructor al que se le tendría que pasar un puntero
	  <varname>this</varname> nulo, para un objeto que no se ha
	  creado <!--Esta es una frase bastante curiosa en el original,
	  que traduzco libremente. -->. He aquí un ejemplo que lo
	  demuestra:
	</para>


//: V1C13:NoMemory.cpp


      <!--
      When the program runs, it does not print the constructor message, only the message from
      operator new( ) and the message in the exception handler. Because new never returns, the
      constructor is never called so its message is not printed.
      -->
	<para>
	  Cuando se ejecuta, el programa imprime los mensajes del
	  <function>operator new()</function> y del manejador de
	  excepción, pero no el del constructor. Como
	  <kw>new</kw> nunca retorna, no se llama al
	  constructor y por tanto no se imprime su mensaje.
	</para>

      <!--
      It’s important that nm be initialized to zero because the new expression never
      completes, and the pointer should be zero to make sure you don’t misuse it. However, you
      should actually do more in the exception handler than just print out a message and
      continue on as if the object had been successfully created. Ideally, you will do
      something that will cause the program to recover from the problem, or at the least exit
      after logging an error.
      -->
	<para>
	  Para asegurar que no se usa indebidamente, Es importante
	  inicializar <varname>nm</varname> a cero, debido a que
	  <kw>new</kw> no se completa. El código de manejo de
	  excepciones debe hacer algo más que imprimir un mensaje y
	  continuar como si el objeto hubiera sido creado con
	  éxito. Idealmente, debería hacer algo que permitiera al
	  programa recuperarse del fallo, o al menos, provocar la salida
	  después de registrar un error.
	</para>


      <!--
      In earlier versions of C++ it was standard practice to return zero from new if storage
      allocation failed. That would prevent construction from occurring. However, if you try
      to return zero from new with a Standard-conforming compiler, it should tell you that you
      ought to throw bad_alloc instead.
      -->
	<para>
	  En las primeras versiones de C++, el comportamiento estándar
	  consistía en hacer que <kw>new</kw> retornara un
	  puntero nulo si la asignación de memoria fallaba. Esto podía
	  impedir que se llamara al constructor. Si se intenta hacer
	  esto con un compilador que sea conforme al estándar actual, le
	  informará de que en lugar de devolver un valor nulo, debe
	  disparar una excepción de tipo <type>bad_alloc</type>.
	</para>

      </sect3>


      <sect3>
      <!-- : placement new & delete -->
	  <title>
	    Operadores <kw>new</kw> y
	    <kw>delete</kw> de [FIXME emplazamiento (situación)]
	  </title>

      <!-- There are two other, less common, uses for overloading operator new( ). -->
	<para>
	  He aquí otros dos usos, menos comunes, para la sobrecarga de
	    <function>operador new()</function>:
	</para>


      <!--
      1. You may want to place an object in a specific location in memory. This is especially
      important with hardware-oriented embedded systems where an object may be synonymous
      with a particular piece of hardware.
      2. You may want to be able to choose from different allocators when calling new.
      -->
	  <orderedlist numeration="arabic">
	    <listitem>
	      <para>
		Puede ocurrir que necesite emplazar un objeto en un
		lugar específico de la memoria.  Esto puede ser
		importante en programas en los que algunos de los
		objetos se refieren o son sinónimos de componentes
		hardware mapeados sobre una zona de la memoria.
	      </para>
	    </listitem>
	    <listitem>
	      <para>
		Si se quiere permitir la elección entre varios
		asignadores de memoria (allocators) en la llamada a
		<kw>new</kw>.
	      </para>
	    </listitem>
	  </orderedlist>

<!--
 Both of these situations are solved with the same mechanism: The
 overloaded operator new( ) can take more than one argument. As
 you\u2019ve seen before, the first argument is always the size of the
 object, which is secretly calculated and passed by the compiler. But the
 other arguments can be anything you want \u2013 the address you want the
 object placed at, a reference to a memory allocation function or object,
 or anything else that is convenient for you.
-->
	<para>
	  Ambas situaciones se resuelven mediante el mismo mecanismo: la
	  función <function>operator new()</function> puede tomar más de
	  un argumento. Como se ha visto, el primer argumento de
	  <kw>new</kw> es siempre el tamaño del objeto,
	  calculado en secreto y pasado por el compilador. El resto de
	  argumentos puede ser de cualquier otro tipo que se necesite:
	  la dirección en la que queremos emplazar el objeto, una
	  referencia a una función de asignación de memoria, o
	  cualquiera otra cosa que se considere conveniente.
	</para>

      <!--
      The way that you pass the extra arguments to operator new( ) during a call may seem
      slightly curious at first. You put the argument list (without the size_t argument, which
      is handled by the compiler) after the keyword new and before the class name of the
      object you’re creating. For example,
      -->
	<para>
	  Al principio puede parecer curioso el modo en que se pasan los
	  argumentos extra al <function>operator
	  new()</function>. Después de la palabra clave
	  <kw>new</kw> y antes del nombre de clase del objeto
	  que se pretende crear, se pone la lista de argumentos, sin
	  contar con el correspondiente al <literal>size_t</literal> del
	  objeto, que le pasa el compilador.  Por ejemplo, la expresión:
	</para>

	<programlisting>
	  X* xp = new(a) X;
	</programlisting>

      <!--
      will pass a as the second argument to operator new( ). Of course, this can work only if
      such an operator new( ) has been declared.
      -->
	<para>
	  pasará <varname>a</varname> como segundo argumento al operador
	  <function>operator new()</function>. Por supuesto, sólo
	  funcionará si ha sido declarado el <function>operator
	  new()</function> adecuado.
	</para>


      <!-- Here’s an example showing how you can place an object at a particular location: -->
	<para>
	  He aquí un ejemplo demostrativo de cómo se usa esto para
	  colocar un objeto en una posición particular:
	</para>


//: V1C13:PlacementOperatorNew.cpp

      <!--
      Notice that operator new only returns the pointer that’s passed to it. Thus, the caller
      decides where the object is going to sit, and the constructor is called for that memory
      as part of the new-expression.
      -->
	<para>
	  Observe que lo único que hace el operador
	  <kw>new</kw> es retornar el puntero que se
	  pasa. Por tanto, es posible especificar la dirección en la
	  que se quiere construir el objeto.
	</para>

      <!--
      Although this example shows only one additional argument, there’s nothing to prevent you
      from adding more if you need them for other purposes.
      -->
	<para>
	  Aunque este ejemplo muestra sólo un argumento adicional, nada
	  impide añadir otros, si se considera conveniente para sus
	  propósitos.
	</para>

		<!--
		A dilemma occurs when you want to destroy the object. There's only
		one version of operator delete, so there's no way to say, "Use
		my special deallocator for this object." You want to call the
		destructor, but you don't want the memory to be released by the
		dynamic memory mechanism because it wasn't allocated on the heap.
		-->
		<para>
		  Al tratar de destruir estos objetos surge un problema.  Sólo hay una
		  versión del operador <kw>delete</kw>, de modo que no hay forma de
		  decir:  "Usa mi función de liberación de memoria para este objeto".
		  Se requiere llamar al destructor, pero sin utilizar el mecanismo de
		  memoria dinámica, ya que el objeto no está alojado en el montículo.
		</para>


		<!--
		The answer is a very special syntax. You can explicitly call the
		destructor, as in
		-->
		<para>
		  La solución tiene una sintaxis muy especial. Se debe llamar
		  explícitamente al destructor, tal como se muestra:
		</para>


<programlisting>
xp->X::~X();  // Llamada explícita al destructor
</programlisting>

<!-- Por aquí me quedé revisando -->


      <!--
      A stern warning is in order here. Some people see this as a way to destroy objects at
      some time before the end of the scope, rather than either adjusting the scope or (more
      correctly) using dynamic object creation if they want the object’s lifetime to be
      determined at runtime. You will have serious problems if you call the destructor this
      way for an ordinary object created on the stack because the destructor will be called
      again at the end of the scope. If you call the destructor this way for an object that
      was created on the heap, the destructor will execute, but the memory won’t be released,
      which probably isn’t what you want. The only reason that the destructor can be called
      explicitly this way is to support the placement syntax for operator new.
      -->
	<para>
	  Hay que hacer una llamada de atención al respecto. Algunas
	  personas ven esto como un modo de destruir objetos en algún
	  momento anterior al determinado por las reglas de ámbito, en
	  lugar de ajustar el ámbito, o más correctamente, en lugar de
	  usar asignación dinámica como medio de determinar la duración
	  del objeto en tiempo de ejecución. Esto es un error, que puede
	  provocar problemas si se trata de destruir de esta manera un
	  objeto ordinario creado en la pila, ya que el destructor será
	  llamado de nuevo cuando se produzca la salida del ámbito
	  correspondiente. Si se llama de esta forma directa al
	  destructor de un objeto creado dinámicamente, se llevará a
	  cabo la destrucción, pero no la liberación del bloque de
	  memoria, lo que probablemente no es lo que se desea. La única
	  razón para este tipo de llamada explícita al destructor es
	  permitir este uso especial del operador
	  <kw>new</kw>, para emplazamiento en memoria.
	</para>


      <!--
      There’s also a placement operator delete that is only called if a constructor for a
      placement new expression throws an exception (so that the memory is automatically
      cleaned up during the exception). The placement operator delete has an argument list
      that corresponds to the placement operator new that is called before the constructor
      throws the exception. This topic will be explored in the exception handling chapter in
      Volume 2.
      -->
	<para>
	  Existe también una forma de operador <kw>delete</kw>
	  de emplazamiento que sólo es llamada en caso de que el
	  constructor dispare una excepción, con lo que la memoria se
	  libera automáticamente durante la excepción. El operador
	  <kw>delete</kw> de emplazamiento usa una lista de
	  argumentos que se corresponde con la del operador
	  <kw>new</kw> de emplazamiento que fue llamado
	  previamente a que el constructor lanzase la excepción. Este
	  asunto se tratará en el Volumen 2, en un capítulo dedicado al
	  tratamiento de excepciones.
	</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <!-- : Summary -->
    <title>Resumen</title>

    <!--
    It’s convenient and optimally efficient to create automatic objects on the stack, but to
    solve the general programming problem you must be able to create and destroy objects at
    any time during a program’s execution, particularly to respond to information from
    outside the program. Although C’s dynamic memory allocation will get storage from the
    heap, it doesn’t provide the ease of use and guaranteed construction necessary in C++.
    By bringing dynamic object creation into the core of the language with new and delete,
    you can create objects on the heap as easily as making them on the stack. In addition,
    you get a great deal of flexibility. You can change the behavior of new and delete if
    they don’t suit your needs, particularly if they aren’t efficient enough. Also, you can
    modify what happens when the heap runs out of storage.
    -->
    <para>
      La creación de objetos en la pila es eficaz y conveniente,
      pero para resolver el problema general de programación es
      necesario poder crear y destruir objetos en cualquier momento
      en tiempo de ejecución, en particular, para que pueda
      responder a la información externa al programa. Aunque C
      ofrece funciones de asignación dinámica, éstas no proporcionan
      la facilidad de uso ni la construcción garantizada de objetos
      que se necesita en C++. Al llevar al núcleo mismo del lenguaje
      gracias al uso de los operadores <kw>new</kw> y
      <kw>delete</kw>, la creación dinámica de objetos se
      hace tan fácil como la creación de objetos en la pila,
      añadiendo además una gran flexibilidad. Se puede modificar el
      comportamiento de <kw>new</kw> y
      <kw>delete</kw> si no se ajusta a los
      requerimientos, particularmente para mejorar la eficiencia, y
      también es posible definir su comportamiento en caso de
      agotarse la memoria libre.
    </para>
  </sect1>

  <sect1>
    <!-- : Exercises -->
    <title>Ejercicios</title>

    <xi:include parse="xml" href="./ejercicios.xml"/>

    <orderedlist numeration="arabic">
    <!--
    1. Create a class Counted that contains an int id and a static int count. The default
    constructor should begin:
    Counted( ) : id(count++) {. It should also print its id and that it’s being created.
    The destructor should print that it’s being destroyed and its id. Test your class.
    2. Prove to yourself that new and delete always call the constructors and destructors
    by creating an object of class Counted (from Exercise 1) with new and destroying it
    with delete. Also create and destroy an array of these objects on the heap.
    3. Create a PStash object and fill it with new objects from Exercise 1. Observe what
    happens when this PStash object goes out of scope and its destructor is called.
    4. Create a vector< Counted*> and fill it with pointers to new Counted objects (from
    Exercise 1). Move through the vector and print the Counted objects, then move
    through again and delete each one.
    5. Repeat Exercise 4, but add a member function f( ) to Counted that prints a message.
    Move through the vector and call f( ) for each object.
-->
      <listitem>
	<para>
	  Crear una clase <classname>Counted</classname> que contenga un
	  <literal>int id</literal> y un <literal>static int
	  count</literal>. El constructor por defecto debe empezar con
	  <literal>Counted():id(count++){</literal>. También deberá
	  mostrar mensajes con su <varname>id</varname>, además de
	  alguno que muestre que se está creando. El destructor debe
	  mostrar que está siendo destruido y su
	  <varname>id</varname>. Probar su funcionamiento.
	</para>
      </listitem>

      <listitem>
	<para>
	  Compruebe que <kw>new</kw> y
	  <kw>delete</kw> llaman siempre a constructores y
	  destructores, creando mediante el uso de
	  <kw>new</kw> un objeto de la clase
	  <classname>Counted</classname> del ejercicio 1, y
	  destruyéndolo después con <kw>delete</kw>. Cree y
	  destruya un vector de <classname>Counted</classname> en el
	  montículo.
	</para>
      </listitem>

      <listitem>
	<para>
	  Cree un objeto de la clase <classname>PStash</classname>, y
	  llénelo de los objetos del ejercicio 1. Observe lo que sucede
	  cuando el objeto <classname>PStash</classname> sale de su
	  ámbito y es llamado su destructor.
	</para>
      </listitem>

      <listitem>
	<para>
	  Cree un vector de <classname>Counted*</classname> y cárguelo
	  con punteros a objetos <classname>Counted</classname>. Recorra
	  el vector llamando imprimiendo cada objeto, repita este paso y
	  elimínelos uno a uno.
	</para>
      </listitem>

      <listitem>
	<para>
	  Repita el ejercicio 4 añadiendo una función miembro
	  <function>f()</function> de <classname>Counted</classname> que
	  muestre un mensaje. Recorra el vector llamando a
	  <function>f()</function> para cada objeto del vector.
	</para>
      </listitem>

<!--
    6. Repeat Exercise 5 using a PStash.
    7. Repeat Exercise 5 using Stack4.h from Chapter 9.
    8. Dynamically create an array of objects of class Counted (from Exercise 1). Call
    delete for the resulting pointer, without the square brackets. Explain the results.
    9. Create an object of class Counted (from Exercise 1) using new, cast the resulting
    pointer to a void*, and delete that. Explain the results.
    10. Execute NewHandler.cpp on your machine to see the resulting count. Calculate the
    amount of free store available for your program.
-->
      <listitem>
	<para>
	  Repita el ejercicio 5 usando un objeto
	  <classname>PStash</classname>.
	</para>
      </listitem>

      <listitem>
	<para>
	  Repita el ejercicio 5 usando <filename>Stack4.h</filename> del
	  capítulo 9.
	</para>
      </listitem>

      <listitem>
	<para>
	  Cree mediante asignación dinámica un vector de objetos de
	  clase <classname>Counted</classname>. Llame a
	  <kw>delete</kw> con el puntero resultante como
	  argumento, sin usar el operador subíndice []. Explique el
	  resultado.
	</para>
      </listitem>

      <listitem>
	<para>
	  Cree un objeto de clase <classname>Counted</classname>
	  mediante <kw>new</kw>, convierta el puntero
	  resultante a <kw>void*</kw> y luego
	  bórrelo. Explique el resultado.
	</para>
      </listitem>

      <listitem>
	<para>
	  Compile y ejecute el programa
	  <filename>NewHandler.cpp</filename> en su ordenador. A partir
	  del número resultante, calcule la cantidad de memoria libre
	  disponible para su programa.
	</para>
      </listitem>

	  <!--
    11. Create a class with an overloaded operator new and delete, both the single-object
    versions and the array versions. Demonstrate that both versions work.
    12. Devise a test for Framis.cpp to show yourself approximately how much faster the
    custom new and delete run than the global new and delete.
    13. Modify NoMemory.cpp so that it contains an array of int and so that it actually
    allocates memory instead of throwing bad_alloc. In main( ), set up a while loop like
    the one in NewHandler.cpp to run out of memory and see what happens if your operator
    new does not test to see if the memory is successfully allocated. Then add the check
    to your operator new and throw bad_alloc.
    14. Create a class with a placement new with a second argument of type string. The class
    should contain a static vector<string> where the second new argument is stored. The
    placement new should allocate storage as normal. In main( ), make calls to your
    placement new with string arguments that describe the calls (you may want to use the
    preprocessor’s __FILE__ and __LINE__ macros).
    15. Modify ArrayOperatorNew.cpp by adding a static vector<Widget*> that adds each Widget
    address that is allocated in operator new( ) and removes it when it is released via
    operator delete( ). (You may need to look up information about vector in your
    Standard C++ Library documentation or in the 2^nd volume of this book, available at
    the Web site.) Create a second class called MemoryChecker that has a destructor that
    prints out the number of Widget pointers in your vector. Create a program with a
    single global instance of MemoryChecker and in main( ), dynamically allocate and
    destroy several objects and arrays of Widget. Show that MemoryChecker reveals memory
    leaks.
    -->

      <listitem>
	<para>
	  Cree una clase y defina en ella operadores de sobrecarga
	  para <kw>new</kw> y <kw>delete</kw>,
	  para objetos simples y para vectores de objetos. Demuestre
	  que ambas versiones funcionan.
	</para>
      </listitem>

      <listitem>
	<para>
	  Diseñe un test que le permita evaluar de forma aproximada la
	  mejora en velocidad obtenida en
	  <filename>Framis.cpp</filename> con el uso de las versiones
	  adaptadas de <kw>new</kw> y
	  <kw>delete</kw>, respecto de la obtenida con las
	  globales .
	</para>
      </listitem>

      <listitem>
	<para>
	  Modifique <filename>NoMemory.cpp</filename> para que contenga
	  un vector de enteros y realmente obtenga memoria en lugar de
	  disparar <classname>bad_alloc</classname>. Establezca un bucle
	  <kw>while</kw> en el cuerpo de
	  <function>main()</function> similar al que existe en
	  <filename>NewHandler.cpp</filename> para agotar la
	  memoria. Observe lo que sucede en el caso de que su operador
	  <kw>new</kw> no compruebe el éxito de la asignación
	  de memoria. Añada después esa comprobación a su operador
	  <kw>new</kw> y la llamada a <literal>throw
	  bad_alloc</literal>.
	</para>
      </listitem>

      <listitem>
	<para>
	  Cree una clase y defina un operador <kw>new</kw> de
	  emplazamiento, con un <type>string</type> como segundo
	  argumento.  Defina un vector de <type>string</type>, en
	  el que se almacenará este segundo argumento a cada llamada a
	  <kw>new</kw>.  El operador <kw>new</kw> de
	  emplazamiento asignará bloques de manera normal.  En
	  <function>main()</function>, haga llamadas a este operador
	  <kw>new</kw> pasándole como argumentos cadenas de
	  caracteres que describan las llamadas. Para ello, puede hacer
	  uso de las macros <constant>__FILE__</constant> y
	  <constant>__LINE__</constant> del preprocesador.
	</para>
      </listitem>

      <listitem>
	<para>
	  Modifique <filename>ArrayOperatorNew.cpp</filename> definiendo
	  un vector estático de <type>Widget*</type> que añada la
	  dirección de cada uno de los objetos
	  <classname>Widget</classname> asignados con
	  <kw>new</kw>, y la retire cuando sea liberada
	  mediante <kw>delete</kw>. Puede que necesite buscar
	  información sebre vectores en la documentación de la
	  biblioteca estándar de C++, o en el segundo volumen de este
	  libro que está disponible en la web del autor. Cree una
	  segunda clase a la que llamará
	  <classname>MemoryChecker</classname>, que contenga un
	  destructor que muestre el número de punteros a
	  <classname>Widget</classname> en su vector. Diseñe un programa
	  con una única instancia global de
	  <classname>MemoryChecker</classname>, y en
	  <function>main()</function>, cree y destruya dinámicamente
	  varios objetos y vectores de objetos
	  <classname>Widget</classname>. Observe que
	  <classname>MemoryCheck</classname> revela fugas de memoria.
	</para>
      </listitem>
    </orderedlist>
  </sect1>

</chapter>


<!-- Informe de la 1ª revisión: David Villa <dvilla@gmx.net>

  Por convenio hay que utilizar la tercera persona del singular para
  referirse al lector. En lugar de "Veremos a continuación" debe usarse
  "Verá a continuación" o "Se verá a continuación"

  Usar "puntero", en lugar de "apuntador".

  new y delete NO son funciones, son palabras clave (<kw>)

  Cuando dice "operator new()" hay que respetarlo porque se refiere al
  método de una clase que lleva ese nombre. No debe traducirse por
  "operador"

  Evitar la pasiva, muy habitual en inglés, pero queda muy forzado en
  castellano


-->


<!-- Local Variables: -->
<!-- coding: utf-8 -->
<!-- fill-column: 90 -->
<!-- mode: flyspell -->
<!-- ispell-local-dictionary: "castellano8" -->
<!-- End: -->