Source

PensarEnC++ / V1-C11.xml

The branch 'PensarEnC++' does not exist.
Full commit
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
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
<?xml  version="1.0" encoding="utf-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 21/PSGML
  Traducción original: Javier Corrales García
  Formateado DocBook:  Javier Corrales García
  1ª Revisión:         David Villa
  2ª Revisión:
-->

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

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

  <title>Las referencias y el constructor de copia</title>

  <highlights>

    <!--
    References are like constant pointers that are automatically
    dereferenced by the compiler.
    -->
    <para>
      Las referencias son como punteros constantes que el compilador
      de-referencia automáticamente.
    </para>
  </highlights>

  <!--
  Although references also exist in Pascal, the C++ version was taken
  from the Algol language. They are essential in C++ to support the
  syntax of operator overloading (see Chapter 12), but they are also a
  general convenience to control the way arguments are passed into and
  out of functions.
  -->
  <para>
    Aunque las referencias también existen en Pascal, la versión de
    C++ se tomó del lenguaje Algol. Las referencias son esenciales en
    C++ para ayudar en la sintaxis de los operadores sobrecargados
    (vea el <link linkend="C12">capítulo 12</link>) y, además, son una
    buena forma para controlar la manera en que los argumentos se
    pasan a las funciones tanto hacia dentro como hacia fuera.
  </para>

  <!--
  This chapter will first look briefly at the differences between
  pointers in C and C++, then introduce references. But the bulk of the
  chapter will delve into a rather confusing issue for the new C++
  programmer: the copy-constructor, a special constructor (requiring
  references) that makes a new object from an existing object of the
  same type. The copy-constructor is used by the compiler to pass and
  return objects by value into and out of functions.
  -->
  <para>
    En este capítulo primero verá la diferencia entre los punteros en
    C y en C++, y luego se presentarán las referencias. Pero la mayor
    parte del capítulo ahondará en el asunto un tanto confuso para los
    programadores de C++ novatos: el constructor de copia, un
    constructor especial (que usa referencias) y construye un nuevo
    objeto de otro ya existente del mismo tipo. El compilador utiliza
    el constructor de copia para pasar y retornar objetos
    <emphasis>por valor</emphasis> a las funciones.
  </para>

  <!-- Finally, the somewhat obscure C++ pointer-to-member feature is illuminated. -->
  <para>
    Finalmente, se hablará sobre la característica (un tanto oscura) de
    los <emphasis>punteros-a-miembro</emphasis> de C++.
  </para>


  <sect1>
    <!-- : Pointers in C++ -->
    <title>Punteros en C++</title>

    <!--
    The most important difference between pointers in C and those in C++
    is that C++ is a more strongly typed language. This stands out where
    void* is concerned. C doesn't let you casually assign a pointer of one
    type to another, but it does allow you to accomplish this through a
    void*. Thus,
    -->
    <para>
      La diferencia más importante entre los punteros en C y en C++ es
      que los de C++ están fuertemente tipados. Sobre todo en lo que
      al tipo <type>void *</type> se refiere. C no permite asignar un
      puntero de un tipo a otro de forma casual, pero
      <emphasis>sí</emphasis> permite hacerlo mediante un <type>void
      *</type>. Por ejemplo,
    </para>

<programlisting>
Bird* b;
Rock* r;
void* v;
v = r;
b = v;
</programlisting>

    <!--
    Because this "feature" of C allows you to quietly treat any type like
    any other type, it leaves a big hole in the type system. C++ doesn't
    allow this; the compiler gives you an error message, and if you really
    want to treat one type as another, you must make it explicit, both to
    the compiler and to the reader, using a cast. (Chapter 3 introduced
    C++'s improved "explicit" casting syntax.)
    -->
    <para>
      A causa de esta <quote>característica</quote> de C, puede
      utilizar cualquier tipo como si de otro se tratara sin ningún
      aviso por parte del compilador. C++ no permite hacer esto; el
      compilador da un mensaje de error, y si realmente quiere
      utilizar un tipo como otro diferente, debe hacerlo
      explícitamente, tanto para el compilador como para el lector,
      usando molde (<emphasis>cast</emphasis> en inglés). (En el <link
      linkend="C03">capítulo 3</link> se habló sobre la sintaxis
      mejorada del molde <quote>explícito</quote>).
    </para>
  </sect1>

  <sect1>
    <!-- : References in C++ -->
    <title>Referencias en C++</title>

    <!--
    A reference (&) is like a constant pointer that is automatically
    dereferenced. It is usually used for function argument lists and
    function return values. But you can also make a free-standing
    reference. For example,
    -->
    <para>
      Una <emphasis>referencia</emphasis> (&amp;) es como un puntero
      constante que se de-referencia automáticamente. Normalmente se
      utiliza en la lista de argumentos y en el valor de retorno de de
      las funciones. Pero también se puede hacer una referencia que
      apunte a algo que no ha sido asignado. Por ejemplo:
    </para>


//: V1C11:FreeStandingReferences.cpp

    <!--
    In line (1), the compiler allocates a piece of storage, initializes it
    with the value 12, and ties the reference to that piece of
    storage. The point is that any reference must be tied to someone
    else's piece of storage. When you access a reference, you're accessing
    that storage. Thus, if you write lines like (2) and (3), then
    incrementing a is actually incrementing x, as is shown in main(
    ). Again, the easiest way to think about a reference is as a fancy
    pointer. One advantage of this "pointer" is that you never have to
    wonder whether it's been initialized (the compiler enforces it) and
    how to dereference it (the compiler does it).
    -->
    <para>
      En la linea (1) el compilador asigna la cantidad necesaria de
      memoria, la inicializa con el valor 12, y liga la referencia a
      esa porción de memoria. Lo importante es que una referencia debe
      estar ligada a la memoria de
      <emphasis>alguien</emphasis>. Cuando se accede a una referencia,
      se está accediendo a esa memoria. Así pues, si escribe las
      lineas (2) y (3) incrementará <varname>x</varname> cuando se
      incremente <varname>a</varname>, tal como se muestra en el
      <function>main()</function>. Lo más fácil es pensar que una
      referencia es como un puntero de lujo. La ventaja de este
      <quote>puntero</quote> es que nunca hay que preguntarse si ha
      sido inicializado (el compilador lo impone) o si hay que
      destruirlo (el compilador lo hace).
    </para>

   <!-- There are certain rules when using references: -->
    <para>
      Hay que seguir unas determinadas reglas cuando se utilizan
      referencias:
      <orderedlist>
	<listitem>
	  <!-- 1. A reference must be initialized when it is
	  created. (Pointers can be initialized at any time.)
	  -->
	  <para>
	    La referencia de ser inicializada cuando se crea. (Los
	    punteros pueden inicializarse en cualquier momento).
	  </para>
	</listitem>
	<listitem>
	  <!-- 2. Once a reference is initialized to an object, it
	  cannot be changed to refer to another object. (Pointers can
	  be pointed to another object at any time.)  -->
	  <para>
	    Una vez que se inicializa una referencia, ligándola a un
	    objeto, no se puede ligar a otro objeto. (Los punteros
	    pueden apuntar a otro objeto en cualquier momento).
	  </para>
	</listitem>
	<listitem>
	  <!-- 3. You cannot have NULL references. You must always be
	  able to assume that a reference is connected to a legitimate
	  piece of storage.  -->
	  <para>
	    No se pueden tener referencias con valor nulo. Siempre ha
	    de suponer que una referencia está conectada a una trozo
	    de memoria ya asignada.
	  </para>
	</listitem>
      </orderedlist>
    </para>

    <sect2>
      <!-- : References in functions -->
      <title>Referencias en las funciones</title>

      <!--
      The most common place you'll see references is as function arguments
      and return values. When a reference is used as a function argument,
      any modification to the reference inside the function will cause
      changes to the argument outside the function. Of course, you could do
      the same thing by passing a pointer, but a reference has much cleaner
      syntax. (You can think of a reference as nothing more than a syntax
      convenience, if you want.)
      -->
      <para>
	El lugar más común en el que verá referencias es en los
	argumentos y valor de retorno de las funciones. Cuando se
	utiliza una referencia como un argumento de una función,
	cualquier cambio realizado en la
	referencia <emphasis>dentro</emphasis> de la función se
	realizará realmente sobre el argumento
	<emphasis>fuera</emphasis> de la función.  Por supuesto que
	podría hacer lo mismo pasando un puntero como argumento, pero
	una referencia es sintácticamente más clara.  (Si lo desea,
	puede pensar que una referencia es, nada más y nada menos,
	más conveniente sintácticamente).
      </para>
      <!--
      If you return a reference from a function, you must take the same care
      as if you return a pointer from a function. Whatever the reference is
      connected to shouldn't go away when the function returns, otherwise
      you'll be referring to unknown memory.
      -->
      <para>
	Si una función retorna una referencia, ha de tener el mismo
	cuidado que si la función retornara un puntero. La referencia
	que se devuelva debe estar ligada a algo que no sea liberado
	cuando la función retorne. Si no, la referencia se referirá a un
	trozo de memoria sobre el que ya no tiene control.
      </para>

      <!-- Here's an example: -->
      <para>
	He aquí un ejemplo:
      </para>


//: V1C11:Reference.cpp

      <!--
      The call to f() doesn't have the convenience and cleanliness of using
      references, but it's clear that an address is being passed. In the
      call to g(), an address is being passed (via a reference), but you
      don't see it.
      -->
      <para>
	La llamada a <function>f()</function> no tiene la ventaja ni la
	claridad que la utilización de referencias, pero está claro que
	se está pasando una dirección mediante un puntero. En la llamada
	a <function>g()</function>, también se pasa una dirección
	(mediante una referencia), pero no se ve.
      </para>
      <sect3>
	<!-- : const references -->
	<title>Referencias constantes</title>

	<!-- The reference argument in Reference.cpp works only when
        the argument is a non-const object. If it is a const object,
        the function g() will not accept the argument, which is
        actually a good thing, because the function does modify the
        outside argument. If you know the function will respect the
        constness of an object, making the argument a const reference
        will allow the function to be used in all situations. This
        means that, for built-in types, the function will not modify
        the argument, and for user-defined types, the function will
        call only const member functions, and won't modify any public
        data members.  -->
	<para>
	  El argumento referencia en
	  <filename>Reference.cpp</filename> funciona solamente en
	  caso de que el argumento no sea un objeto constante.  Si
	  fuera un objeto constante, la función
	  <function>g()</function> no aceptaría el argumento, lo cual
	  es positivo porque la función
	  <emphasis>modificaría</emphasis> el argumento que está fuera
	  de la función. Si sabe que la función respetará las
	  constancia un objeto, el hecho de que el argumento sea una
	  referencia constante permitirá que la función se pueda
	  utilizar en cualquier situación. Esto significa que para
	  tipos predefinidos, la función no modificará el argumento, y
	  para tipos definidos por el usuario, la función llamará
	  solamente a métodos constantes, y no modificara ningún
	  atributo público.
	</para>

        <!--
        The use of const references in function arguments is especially
        important because your function may receive a temporary object. This
        might have been created as a return value of another function or
        explicitly by the user of your function. Temporary objects are always
        const, so if you don't use a const reference, that argument won't be
        accepted by the compiler. As a very simple example,
        -->
	<para>
	  La utilización de referencias constantes en argumentos de
	  funciones es especialmente importante porque una función
	  puede recibir un objeto temporal. Éste podría haber sido
	  creado como valor de retorno de otra función o
	  explícitamente por el usuario de la función. Los objetos
	  temporales son siempre constantes.  Por eso, si no utiliza
	  una referencia constante, el compilador se quejará. Como
	  ejemplo muy simple:
	</para>


//: V1C11:ConstReferenceArguments.cpp

        <!--
        The call to f(1) causes a compile-time error because the compiler must
        first create a reference. It does so by allocating storage for an int,
        initializing it to one and producing the address to bind to the
        reference. The storage must be a const because changing it would make
        no sense - you can never get your hands on it again. With all
        temporary objects you must make the same assumption: that they're
        inaccessible. It's valuable for the compiler to tell you when you're
        changing such data because the result would be lost information.
        -->
	<para>
	  La llamada <code>f(1)</code> provoca un error en tiempo de
	  compilación porque el compilador debe crear primero una
	  referencia. Lo hace asignando memoria para un
	  <type>int</type>, iniciánlizándolo a uno y generando la
	  dirección de memoria para ligarla a la referencia. La
	  memoria debe ser constante porque no
	  tendría sentido cambiarlo: no puede cambiarse de
	  nuevo. Puede hacer la misma suposición para todos los
	  objetos temporales: son inaccesibles. Es importante
	  que el compilador le diga cuándo está intentando cambiar
	  algo de este estilo porque podría perder información.
	</para>

      </sect3>
      <sect3>
	<!-- : Pointer references -->
	<title>Referencias a puntero</title>

	<!--
        In C, if you want to modify the contents of the pointer rather than
        what it points to, your function declaration looks like:
        -->
	<para>
	  En C, si desea modificar el <emphasis>contenido</emphasis> del
	  puntero en sí en vez de modificar a lo que apunta, la
	  declaración de la función sería:
	</para>


<programlisting>
void f(int**);
</programlisting>


	<para>
	  <!-- and you'd have to take the address of the pointer when passing it in: -->
	  y tendría que tomar la dirección del puntero cuando se llamara
	  a la función:
	</para>


<programlisting>
int i = 47;
int* ip = &amp;i;
f(&amp;ip);
</programlisting>

	<!--
        With references in C++, the syntax is cleaner. The function argument
        becomes a reference to a pointer, and you no longer have to take the
        address of that pointer. Thus,
        -->
	<para>
	  La sintaxis es más clara con las referencias en C++. El
	  argumento de la función pasa a ser de una referencia a un
	  puntero, y así no ha de manejar la dirección del puntero.
	</para>


//: V1C11:ReferenceToPointer.cpp

        <!--
        By running this program, you'll prove to yourself that the pointer is
        incremented, not what it points to.
        -->
	<para>
	  Al ejecutar este programa se observa que el puntero se
	  incrementa en vez de incrementar a lo que apunta.
	</para>
      </sect3>
    </sect2>


    <sect2>
      <!-- : Argument-passing guidelines -->
      <title>Consejos para el paso de argumentos</title>

      <!-- Your normal habit when passing an argument to a function
      should be to pass by const reference. Although at first this may
      seem like only an efficiency concern (and you normally don't
      want to concern yourself with efficiency tuning while you're
      designing and assembling your program), there's more at stake:
      as you'll see in the remainder of the chapter, a
      copy-constructor is required to pass an object by value, and
      this isn't always available.  -->
      <para>
	Cuando se pasa un argumento a un función, lo normal debería
	ser pasarlo como una referencia constante. Aunque al principio
	puede parecer que sólo tiene ventajas en términos de eficacia
	(y normalmente en diseño e implementación inicial no se tiene
	muy en cuenta la eficacia), además tiene otras: como se podrá
	ver en el resto del capítulo, se requiere un constructor de
	copia para pasar un objeto por valor, y esto no siempre es
	posible.
      </para>

      <!-- The efficiency savings can be substantial for such a simple
	habit: to pass an argument by value requires a constructor and
	destructor call, but if you're not going to modify the
	argument then passing by const reference only needs an address
	pushed on the stack.  -->
      <para>
	La eficacia puede mejorar substancialmente por este simple
	hábito: pasar un argumento por valor necesita una llamada a un
	constructor y otra a un destructor, pero si no se va a
	modificar el argumento, el hecho de pasarlo como una
	referencia constante sólo necesita poner una dirección en la
	pila.
      </para>

      <!-- In fact, virtually the only time passing an address isn't
	preferable is when you're going to do such damage to an object
	that passing by value is the only safe approach (rather than
	modifying the outside object, something the caller doesn't
	usually expect). This is the subject of the next section.  -->
      <para>
	De hecho, prácticamente la única situación en la que no es
	preferible pasar la dirección, es cuando provocará tales
	problemas a un objeto que pasar por valor es la única
	alternativa segura (en vez de modificar el objeto que está
	fuera del ámbito de la función, algo que el que llama a la
	función normalmente no espera). Ese es el tema de la
	siguiente sección.
      </para>
    </sect2>
  </sect1>

  <sect1>
    <!-- : The copy-constructor -->
    <title>El constructor de copia</title>

    <!-- Now that you understand the basics of the reference in C++,
    you're ready to tackle one of the more confusing concepts in the
    language: the copy-constructor, often called X(X&) ("X of X
    ref"). This constructor is essential to control passing and
    returning of user-defined types by value during function
    calls. It's so important, in fact, that the compiler will
    automatically synthesize a copy-constructor if you don't provide
    one yourself, as you will see.  -->
    <para>
      Ahora que entiende lo básico de las referencias en C++, está
      preparado para tratar uno de los conceptos más confusos del
      lenguaje: el constructor de copia, a menudo denominado
      <code>X(X&amp;)</code> (<quote>X de la referencia
      X</quote>). Este constructor es esencial para controlar el paso
      y retorno por valor de los tipos definidos por el usuario en las
      llamadas a funciones. De hecho es tan importante que el
      compilador crea automáticamente un constructor de copia en caso
      de que el programador no lo proporcione.
    </para>

    <sect2>
      <!-- : Passing & returning by value -->
      <title>Paso y retorno por valor</title>

      <!-- To understand the need for the copy-constructor, consider
      the way C handles passing and returning variables by value
      during function calls. If you declare a function and make a
      function call, -->
      <para>
	Para entender la necesidad del constructor de copia, considere la
	forma en que C maneja el paso y retorno por valor de variables
	cuando se llama a una función. Si declara una función y la
	invoca,
      </para>


<programlisting>
int f(int x, char c);
int g = f(a, b);
</programlisting>


      <!--
      how does the compiler know how to pass and return those variables? It
      just knows! The range of the types it must deal with is so small -
      char, int, float, double, and their variations - that this information
      is built into the compiler.
      -->
      <para>
	¿cómo sabe el compilador cómo pasar y retornar esas variables?
	¡Simplemente lo sabe! El rango de tipos con los que debe
	tratar es tan pequeño (<type>char</type>, <type>int</type>,
	<type>float</type>, <type>double</type>, y sus variaciones),
	que tal información ya está dentro del compilador.
      </para>

      <!-- If you figure out how to generate assembly code with your
      compiler and determine the statements generated by the function
      call to f(), you'll get the equivalent of: -->
      <para>
	Si averigua cómo hacer que su compilador genere código
	ensamblador y determina qué instrucciones se usan para la
	invocación de la función <function>f()</function>, obtendrá
	algo equivalente a:
      </para>


<programlisting>
push  b
push  a
call  f()
add  sp, 4
mov  g, register a
</programlisting>

      <!--
      This code has been cleaned up significantly to make it generic; the
      expressions for b and a will be different depending on whether the
      variables are global (in which case they will be _b and _a) or local
      (the compiler will index them off the stack pointer). This is also
      true for the expression for g. The appearance of the call to f() will
      depend on your name-decoration scheme, and "register a" depends on how
      the CPU registers are named within your assembler. The logic behind
      the code, however, will remain the same.
      -->
      <para>
	Este código se ha simplificado para hacerlo genérico; las
        expresiones <varname>b</varname> y <varname>a</varname> serán
        diferentes dependiendo de si las variables son globales (en
        cuyo caso serían <varname>_b</varname> y
        <varname>_a</varname>) o locales (el compilador las pondría en
        la pila). Esto también es cierto para <varname>g</varname>. La
        sintaxis de la llamada a <function>f()</function> dependería
        de su guía de estilo, y <code>register a</code> dependería de
        cómo su ensamblador llama a los registros de la CPU. A pesar
        de la simplificación, la lógica del código sería la misma.
      </para>

      <!-- In C and C++, arguments are first pushed on the stack from
        right to left, then the function call is made. The calling
        code is responsible for cleaning the arguments off the stack
        (which accounts for the add sp,4). But notice that to pass the
        arguments by value, the compiler simply pushes copies on the
        stack - it knows how big they are and that pushing those
        arguments makes accurate copies of them.  -->
      <para>
	Tanto en C como en C++, primero se ponen los argumentos en la
	pila de derecha a izquierda, y luego se llama a la función. El
	código de llamada es responsable de recoger los argumentos de
	la pila (lo cual explica la sentencia <code>add sp, 4</code>).
	Pero tenga en cuenta que cuando se pasan argumentos por valor,
	el compilador simplemente pone copias en la pila (conoce los
	tamaños de cada uno, por lo que los puede copiar).
	</para>

      <!-- The return value of f() is placed in a register. Again, the
	compiler knows everything there is to know about the return
	value type because that type is built into the language, so
	the compiler can return it by placing it in a register. With
	the primitive data types in C, the simple act of copying the
	bits of the value is equivalent to copying the object.  -->
      <para>
	El valor de retorno de <function>f()</function> se coloca en un
	registro. Como el compilador sabe lo que se está retornando,
	porque la información del tipo ya está en el lenguaje, puede
	retornarlo colocándolo en un registro. En C, con tipos
	primitivos, el simple hecho de copiar los bits del valor es
	equivalente a copiar el objeto.
      </para>

      <sect3>
	<!-- : Passing & returning large objects -->
	<title>Paso y retorno de objetos grandes</title>

	<!-- But now consider user-defined types. If you create a
        class and you want to pass an object of that class by value,
        how is the compiler supposed to know what to do? This is not a
        type built into the compiler; it's a type you have created.
        -->
	<para>
	  Considere ahora los tipos definidos por el usuario. Si crea
	  una clase y desea pasar un objeto de esa clase por valor,
	  ¿cómo sabe el compilador lo que tiene que hacer?  La
	  información de la clase no está en el compilador, pues lo ha
	  definido el usuario.
	</para>

	<!-- To investigate this, you can start with a simple
        structure that is clearly too large to return in registers:
        -->
	<para>
	  Para investigar esto, puede empezar con una estructura simple
	  que, claramente, es demasiado grande para ser devuelta a
	  través de los registros:
	</para>


//: V1C11:PassingBigStructures.cpp


        <!--
        Decoding the assembly output is a little more complicated here because
        most compilers use "helper" functions instead of putting all
        functionality inline. In main(), the call to bigfun() starts as you
        might guess - the entire contents of B is pushed on the stack. (Here,
        you might see some compilers load registers with the address of the
        Big and its size, then call a helper function to push the Big onto the
        stack.)
        -->
	<para>
	  La conversión a código ensamblador es un poco más complicada
	  porque la mayoría de los compiladores utilizan funciones
	  <quote>auxiliares</quote>
	  (<foreignphrase>helper</foreignphrase>) en vez de inline. En
	  la función <function>main()</function>, la llamada a
	  <function>bigfun()</function> empieza como debe: se coloca
	  el contenido de <varname>B</varname> en la pila. (Aquí
	  podría ocurrir que algunos compiladores carguen registros
	  con la dirección y tamaño de <classname>Big</classname> y
	  luego una función auxiliar se encargue de colocar el
	  <classname>Big</classname> en la pila).
	</para>

	<!-- In the previous code fragment, pushing the arguments onto
        the stack was all that was required before making the function
        call. In PassingBigStructures.cpp, however, you'll see an
        additional action: the address of B2 is pushed before making
        the call, even though it's obviously not an argument. To
        comprehend what's going on here, you need to understand the
        constraints on the compiler when it's making a function call.
        -->
	<para>
	  En el fragmento de código fuente anterior, lo único
	  necesario antes de llamar a la función es colocar los
	  argumentos en la pila. Sin embargo, en el código ensamblador
	  de <filename>PassingBigStructures.cpp</filename> se ve una
	  acción adicional: la dirección de <varname>B2</varname> se
	  coloca en la pila antes de hacer la llamada a la función
	  aunque, obviamente, no sea un argumento. Para entender qué
	  pasa, necesita entender las restricciones del compilador
	  cuando llama a una función.
	</para>
      </sect3>

      <sect3>
        <!-- : Function-call stack frame -->
	<title>Marco de pila para llamadas a función</title>

	<!-- When the compiler generates code for a function call, it
        first pushes all the arguments on the stack, then makes the
        call. Inside the function, code is generated to move the stack
        pointer down even farther to provide storage for the
        function's local variables. ("Down" is relative here; your
        machine may increment or decrement the stack pointer during a
        push.) But during the assembly-language CALL, the CPU pushes
        the address in the program code where the function call came
        from, so the assembly-language RETURN can use that address to
        return to the calling point. This address is of course sacred,
        because without it your program will get completely
        lost. Here's what the stack frame looks like after the CALL
        and the allocation of local variable storage in the function:
        -->
	<para>
	  Cuando el compilador genera código para llamar a una
	  función, primero coloca en la pila todos los argumentos y
	  luego hace la llamada. Dentro de la función se genera código
	  para mover el puntero de pila hacia abajo, y así proporciona
	  memoria para las variables locales dentro de la función.
	  (<quote>hacia abajo</quote> es relativo, la máquina puede
	  incrementar o decrementar el puntero de pila al colocar un
	  argumento). Pero cuando se hace el <code>CALL</code> de
	  ensamblador para llamar a la función, la CPU coloca la
	  dirección desde la que se realiza la llamada, y en el
	  <code>RETURN</code> de ensamblador se utiliza esa dirección
	  para volver al punto desde donde se realizó la llamada. Esta
	  dirección es sagrada, porque sin ella el programa se
	  perdería por completo. He aquí es aspecto del marco de pila
	  después de ejecutar <code>CALL</code> y poner las variables
	  locales de la función:
	</para>

	<figure>
	  <title>Llamada a una función</title>
	  <mediaobject>
	    <imageobject role="latex">
	      <imagedata fileref="./images/V1_14.pdf" align="center" format="PDF"/>
	    </imageobject>
	    <imageobject role="html">
	      <imagedata fileref="./images/V1_14.png" align="center" format="PNG"/>
	    </imageobject>
	  </mediaobject>
	</figure>

        <!--
        The code generated for the rest of the function expects the memory to
        be laid out exactly this way, so that it can carefully pick from the
        function arguments and local variables without touching the return
        address. I shall call this block of memory, which is everything used
        by a function in the process of the function call, the function frame.
        -->
	<para>
	  El código generado por el resto de la función espera que la
	  memoria tenga esta disposición para que pueda utilizar los
	  argumentos y las variables locales sin tocar la dirección de
	  retorno. Llámese a este bloque de memoria, que es todo lo
	  que una función necesita cuando se la llama, <emphasis>el
	  marco de la función</emphasis> (<foreignphrase>function
	  frame</foreignphrase>).
	</para>

        <!-- You might think it reasonable to try to return values on
        the stack. The compiler could simply push it, and the function
        could return an offset to indicate how far down in the stack
        the return value begins.  -->
	<para>
	  Podría parecer razonable retornar valores mediante la
	  utilización de la pila. El compilador simplemente los
	  colocaría allí y la función devolvería un desplazamiento que
	  indicara dónde empieza el valor de retorno.
	</para>
      </sect3>

      <sect3>
	<!-- Re-entrancy -->
	<title>Re-entrada</title>

	<!-- The problem occurs because functions in C and C++ support
        interrupts; that is, the languages are re-entrant. They also
        support recursive function calls. This means that at any point
        in the execution of a program an interrupt can occur without
        breaking the program. Of course, the person who writes the
        interrupt service routine (ISR) is responsible for saving and
        restoring all the registers that are used in the ISR, but if
        the ISR needs to use any memory further down on the stack,
        this must be a safe thing to do. (You can think of an ISR as
        an ordinary function with no arguments and void return value
        that saves and restores the CPU state. An ISR function call is
        triggered by some hardware event instead of an explicit call
        from within a program.)  -->
	<para>
	  Este problema ocurre porque las funciones en C y C++ pueden
	  sufrir interrupciones; esto es, los lenguajes han de ser (y
	  de hecho son) <emphasis>re-entrantes</emphasis>. También
	  permiten llamadas a funciones recursivas. Esto quiere decir
	  que en cualquier punto de ejecución de un programa puede
	  sufrir una interrupción sin que el programa se vea afectado
	  por ello. Obviamente la persona que escribe la rutina de
	  servicio de interrupciones (ISR) es responsable de guardar y
	  restaurar todos los registros que se utilicen en la
	  ISR. Pero si la ISR necesita utilizar la pila, ha de hacerlo
	  con seguridad. (Piense que una ISR es como una función
	  normal sin argumentos y con valor de retorno
	  <type>void</type> que guarda y restaura el estado de la
	  CPU. La ejecución de una ISR suele producirse por un evento
	  hardware, y no con una invocación dentro del programa de
	  forma explícita).
	</para>

	<!-- Now imagine what would happen if an ordinary function
        tried to return values on the stack. You can't touch any part
        of the stack that's above the return address, so the function
        would have to push the values below the return address. But
        when the assembly-language RETURN is executed, the stack
        pointer must be pointing to the return address (or right below
        it, depending on your machine), so right before the RETURN,
        the function must move the stack pointer up, thus clearing off
        all its local variables. If you're trying to return values on
        the stack below the return address, you become vulnerable at
        that moment because an interrupt could come along. The ISR
        would move the stack pointer down to hold its return address
        and its local variables and overwrite your return value.  -->
	<para>
	  Ahora imagine que pasaría si una función normal intentara
	  retornar valores mediante la pila. No puede tocar la pila
	  por encima del la dirección de retorno, así que la función
	  tendría que colocar los valores de retorno debajo de la
	  dirección de retorno. Pero cuando se ejecuta el
	  <code>RETURN</code>, el puntero de pila debería estar
	  apuntando a la dirección de retorno (o justo debajo, depende
	  de la máquina), así que la función debe subir el puntero de
	  la pila, desechando todas las variables locales. Si intenta
	  retornar valores usando la pila por debajo de la dirección
	  de retorno, en ese momento es vulnerable a una
	  interrupción. La ISR escribiría encima de los valores de
	  retorno para colocar su dirección de retorno y sus
	  variables locales.
	</para>

	<!-- To solve this problem, the caller could be responsible
        for allocating the extra storage on the stack for the return
        values before calling the function. However, C was not
        designed this way, and C++ must be compatible. As you'll see
        shortly, the C++ compiler uses a more efficient scheme.  -->
	<para>
	  Para resolver este problema, el que llama a la función
	  <emphasis>podría</emphasis> hacerse responsable de asignar
	  la memoria extra en la pila para los valores de retorno
	  antes de llamar a la función. Sin embargo, C no se diseñó de
	  esta manera y C++ ha de ser compatible. Como verá pronto, el
	  compilador de C++ utiliza un esquema más eficaz.
	</para>

	<!-- Your next idea might be to return the value in some
        global data area, but this doesn't work either. Reentrancy
        means that any function can be an interrupt routine for any
        other function, including the same function you're currently
        inside. Thus, if you put the return value in a global area,
        you might return into the same function, which would overwrite
        that return value. The same logic applies to recursion.  -->
	<para>
	  Otra idea sería retornar el valor utilizando un área de
	  datos global, pero tampoco funcionaría. La re-entrada
	  significa que cualquier función puede ser una rutina de
	  interrupción para otra función, <emphasis>incluida la
	  función que se está ejecutando</emphasis>. Por lo tanto, si
	  coloca un valor de retorno en un área global, podría
	  retornar a la misma función, lo cual sobreescribiría el
	  valor de retorno. La misma lógica se aplica a la
	  recursividad.
	</para>

	<!-- The only safe place to return values is in the registers,
        so you're back to the problem of what to do when the registers
        aren't large enough to hold the return value. The answer is to
        push the address of the return value's destination on the
        stack as one of the function arguments, and let the function
        copy the return information directly into the
        destination. This not only solves all the problems, it's more
        efficient. It's also the reason that, in
        PassingBigStructures.cpp, the compiler pushes the address of
        B2 before the call to bigfun() in main(). If you look at the
        assembly output for bigfun(), you can see it expects this
        hidden argument and performs the copy to the destination
        inside the function.  -->
	<para>
	  Los registros son el único lugar seguro para devolver
	  valores, así que se vuelve al problema de qué hacer cuando
	  los registros no son lo suficientemente grandes para
	  contener el valor de retorno. La respuesta es colocar la
	  dirección de la ubicación del valor de retorno en la pila
	  como uno de los argumentos de la función, y dejar que la
	  función copie la información que se devuelve directamente en
	  esa ubicación. Esto no solo soluciona todo los problemas, si
	  no que además es más eficaz. Ésta es la razón por la que el
	  compilador coloca la dirección de <varname>B2</varname>
	  antes de llamar a <function>bigfun</function> en la función
	  <function>main()</function> de
	  <filename>PassingBigStructures.cpp</filename>.  Si viera el
	  código ensamblador de <function>bigfun()</function>
	  observaría que la función espera este argumento escondido y
	  lo copia al destino <emphasis>dentro</emphasis> de la
	  función.
	</para>
      </sect3>

      <sect3>
        <!-- : Bitcopy versus initialization -->
	<title>Copia bit a bit vs. inicialización</title>

	<!-- So far, so good. There's a workable process for passing
        and returning large simple structures. But notice that all you
        have is a way to copy the bits from one place to another,
        which certainly works fine for the primitive way that C looks
        at variables. But in C++ objects can be much more
        sophisticated than a patch of bits; they have meaning. This
        meaning may not respond well to having its bits copied.  -->

        <para>
	  Hasta aquí, todo bien. Tenemos un procedimiento para
	  pasar y retornar estructuras simples grandes. Pero note que
	  lo único que tiene es una manera de copiar bits de un
	  lugar a otro, lo que ciertamente funciona bien para la forma
	  (muy primitiva) en que C trata las variables. Sin embargo,
	  en C++ los objetos pueden ser mucho más avanzados que un
	  puñado de bits, pues tienen significado y, por lo tanto,
	  puede que no responda bien al ser copiado.
	</para>

        <!--
        Consider a simple example: a class that knows how many objects of its
        type exist at any one time. From Chapter 10, you know the way to do
        this is by including a static data member:
        -->
	<para>
	  Considere un ejemplo simple: una clase que conoce cuantos
	  objetos de un tipo existen en cualquier momento. En el <link
	  linkend="C10">Capítulo 10</link> se vio la manera de hacerlo
	  incluyendo un atributo estático (<kw>static</kw>):
	</para>


//: V1C11:HowMany.cpp

        <!--
        The class HowMany contains a static int objectCount and a static
        member function print() to report the value of that objectCount,
        along with an optional message argument. The constructor increments
        the count each time an object is created, and the destructor
        decrements it.
        -->
	<para>
	  La clase <classname>HowMany</classname> contiene un entero
	  estático llamado <varname>objectCount</varname> y un método
	  estático llamado <function>print()</function> para
	  representar el valor de <varname>objectCount</varname>,
	  junto con argumento de mensaje opcional. El constructor
	  incrementa <varname>objectCount</varname> cada vez que se
	  crea un objeto, y el destructor lo disminuye.
	</para>

	<para>
	  Sin embargo la salida no es la que cabría esperar:
	</para>

<screen>
after construction of h: objectCount = 1
x argument inside f(): objectCount = 1
~HowMany(): objectCount = 0
after call to f(): objectCount = 0
~HowMany(): objectCount = -1
~HowMany(): objectCount = -2
</screen>

        <!--
        After h is created, the object count is one, which is fine. But after
        the call to f() you would expect to have an object count of two,
        because h2 is now in scope as well. Instead, the count is zero, which
        indicates something has gone horribly wrong. This is confirmed by the
        fact that the two destructors at the end make the object count go
        negative, something that should never happen.
        -->
	  <para>
	  Después de crear <varname>h</varname>, el contador es uno,
	  lo cual está bien. Pero después de la llamada a
	  <function>f()</function> se esperaría que el contador
	  estuviera a dos, porque <varname>h2</varname> está ahora
	  también dentro de ámbito. Sin embargo, el contador es cero,
	  lo cual indica que algo ha ido muy mal. Esto se confirma por
	  el hecho de que los dos destructores, llamados al final de
	  <function>main()</function>, hacen que el contador pase a ser
	  negativo, algo que no debería ocurrir nunca.
	</para>

	<!--
        Look at the point inside f(), which occurs after the argument is
        passed by value. This means the original object h exists outside the
        function frame, and there's an additional object inside the function
        frame, which is the copy that has been passed by value. However, the
        argument has been passed using C's primitive notion of bitcopying,
        whereas the C++ HowMany class requires true initialization to maintain
        its integrity, so the default bitcopy fails to produce the desired
        effect.
        -->
	<para>
	  Mire lo que ocurre dentro de <function>f()</function>
	  después de que el argumento se pase por valor. Esto quiere
	  decir que el objeto original <varname>h</varname> existe
	  fuera del ámbito de la función y, por otro lado, hay un
	  objeto de más <emphasis>dentro</emphasis> del ámbito de la
	  función, que es copia del objeto que se pasó por valor. El
	  argumento que se pasó utiliza el primitivo concepto de copia
	  bit a bit de C, pero la clase C++
	  <classname>HowMany</classname> necesita inicializarse
	  correctamente para mantener su integridad. Por lo tanto, se
	  demuestra que la copia bit a bit no logra el efecto deseado.
	</para>

	<!-- When the local object goes out of scope at the
	  end of the call to f( ), the destructor is called, which
	  decrements objectCount, so outside the function, objectCount
	  is zero. The creation of h2 is also performed using a
	  bitcopy, so the constructor isn't called there either, and
	  when h and h2 go out of scope, their destructors cause the
	  negative values of objectCount.  -->
	<para>
	  Cuando el objeto local sale de ámbito al acabar la función
	  <function>f()</function>, se llama a su destructor, lo cual
	  decrementa <varname>objectCount</varname>, y por lo tanto el
	  <varname>objectCount</varname> se pone a cero. La creación
	  de <varname>h2</varname> se realiza también mediante la
	  copia bit a bit, así que tampoco se llama al constructor, y
	  cuando <varname>h</varname> y <varname>h2</varname> salen de
	  ámbito, sus destructores causan el valor negativo en
	  <varname>objectCount</varname>.
	</para>
      </sect3>
    </sect2>
    <sect2>
      <!-- : Copy-construction -->
      <title>Construcción por copia</title>

      <!-- The problem occurs because the compiler makes an assumption
      about how to create a new object from an existing object. When
      you pass an object by value, you create a new object, the passed
      object inside the function frame, from an existing object, the
      original object outside the function frame. This is also often
      true when returning an object from a function. In the expression
      -->
      <para>
	El problema se produce debido a que el compilador hace una
	suposición sobre cómo crear <emphasis>un nuevo objeto a partir
	de de otro existente</emphasis>. Cuando se pasa un objeto por
	valor, se crea un nuevo objeto, que estará dentro del ámbito
	de la función, a partir del objeto original existente fuera
	del ámbito de la función. Esto también se puede aplicar a
	menudo cuando una función retorna un objeto. En la expresión
      </para>

<programlisting>
HowMany h2 = f(h);
</programlisting>

      <!--
      h2, a previously unconstructed object, is created from the return
      value of f(), so again a new object is created from an existing one.
      -->
      <para>
	<varname>h2</varname>, un objeto que no estaba creado
	anteriormente, se crea a partir del valor que retorna
	<function>f()</function>; por tanto también se crea un nuevo
	objeto a partir de otro existente.
      </para>

      <!-- The compiler's assumption is that you want to perform this
	creation using a bitcopy, and in many cases this may work
	fine, but in HowMany it doesn't fly because the meaning of
	initialization goes beyond simply copying. Another common
	example occurs if the class contains pointers - what do they
	point to, and should you copy them or should they be connected
	to some new piece of memory?
      -->
      <para>
	El compilador supone que la creación ha de hacerse con una
	copia bit a bit, lo que en muchos casos funciona bien, pero en
	<classname>HowMany</classname> no funciona porque la
	inicialización va más allá de una simple copia. Otro ejemplo
	muy común ocurre cuando la clase contiene punteros pues, ¿a
	qué deben apuntar? ¿debería copiar sólo los punteros o
	debería asignar memoria nueva y que apuntaran a ella?
      </para>

      <!-- Fortunately, you can intervene in this process and prevent
	the compiler from doing a bitcopy. You do this by defining
	your own function to be used whenever the compiler needs to
	make a new object from an existing object. Logically enough,
	you're making a new object, so this function is a constructor,
	and also logically enough,
      the single argument to this
	constructor has to do with the object you're constructing
	from. But that object can't be passed into the constructor by
	value because you're trying to define the function that
	handles passing by value, and syntactically it doesn't make
	sense to pass a pointer because, after all, you're creating
	the new object from an existing object. Here, references come
	to the rescue, so you take the reference of the source
	object. This function is called the copy-constructor and is
	often referred to as X(X&), which is its appearance for a
	class called X.  -->
      <para>
	Afortunadamente, puede intervenir en este proceso e impedir
	que el compilador haga una copia bit a bit. Se soluciona
	definiendo su propia función cuando el compilador necesite
	crear un nuevo objeto a partir de otro. Lógicamente, está
	creando un nuevo objeto, por lo que esta función es un
	constructor, y el único argumento del constructor tiene que
	ver con el objeto del que se pretende partir para crear el
	nuevo. Pero no puede pasar ese objeto por valor al constructor
	porque está intentando <emphasis>definir</emphasis> la función
	que maneja el paso por valor, y, por otro lado,
	sintácticamente no tiene sentido pasar un puntero porque,
	después de todo, está creando un objeto a partir de de
	otro. Aquí es cuando las referencias vienen al rescate, y
	puede utilizar la referencia del objeto origen. Esta función
	se llama <emphasis>constructor de copia</emphasis>, que
	también se lo puede encontrar como
	<function>X(X&amp;)</function>, que es el constructor de copia
	de una clase llamada <classname>X</classname>.
      </para>

      <!-- If you create a copy-constructor, the compiler will not
      perform a bitcopy when creating a new object from an existing
      one. It will always call your copy-constructor. So, if you don't
      create a copy-constructor, the compiler will do something
      sensible, but you have the choice of taking over complete
      control of the process.  -->
      <para>
	Si crea un constructor de copia, el compilador no realizará
	una copia bit a bit cuando cree un nuevo objeto a partir de
	otro.  El compilador siempre llamará al constructor de
	copia. Si no crea el constructor de copia, el compilador
	intentará hacer algo razonable, pero usted tiene la opción de
	tener control total del proceso.
      </para>

      <!-- Now it's possible to fix the problem in HowMany.cpp: -->
      <para>
	Ahora es posible solucionar el problema en
	<filename>HowMany.cpp</filename>:
      </para>


//: V1C11:HowMany2.cpp

      <!--
      There are a number of new twists thrown in here so you can get a
      better idea of what's happening. First, the string name acts as an
      object identifier when information about that object is printed. In
      the constructor, you can put an identifier string (usually the name of
      the object) that is copied to name using the string constructor. The
      default = "" creates an empty string. The constructor increments the
      objectCount as before, and the destructor decrements it.
      -->
      <para>
	Hay unas cuantas cosas nuevas para que pueda hacerse una idea
	mejor de lo que pasa. Primeramente, el <code>string
	name</code> hace de identificador de objeto cuando se imprima
	en la salida.  Puede poner un identificador (normalmente el
	nombre del objeto) en el constructor para que se copie en
	<varname>name</varname> utilizando el constructor con un
	<type>string</type> como argumento. Por defecto se crea un
	<type>string</type> vacío. El constructor incrementa
	<varname>objectCount</varname> y el destructor lo disminuye,
	igual que en el ejemplo anterior.
      </para>

      <!-- Next is the copy-constructor, HowMany2(const
	HowMany2&). The copy-constructor can create a new object only
	from an existing one, so the existing object's name is copied
	to name, followed by the word "copy" so you can see where it
	came from. If you look closely, you'll see that the call
	name(h.name) in the constructor initializer list is actually
	calling the string copy-constructor.  -->
      <para>
	Lo siguiente es el constructor de copia,
	<function>HowMany2(const HowMany2&amp;)</function>. El
	constructor de copia simplemente crea un objeto a partir de
	otro existente, así que copia en <varname>name</varname> el
	identificador del objeto origen, seguido de la palabra
	<quote>copy</quote>, y así puede ver de dónde procede.  Si
	mira atentamente, verá que la llamada
	<code>name(h.name)</code> en la lista de inicializadores del
	constructor está llamando al constructor de copia de la clase
	<type>string</type>.
      </para>

      <!-- Inside the copy-constructor, the object count is
	incremented just as it is inside the normal constructor. This
	means you'll now get an accurate object count when passing and
	returning by value.  -->
      <para>
	Dentro del constructor de copia, se incrementa el contador
	igual que en el constructor normal. Esto quiere decir que
	obtendrá un contador de objetos preciso cuando pase y retorne
	por valor.
      </para>

	<!-- The print() function has been modified to print out a
      message, the object identifier, and the object count. It must
      now access the name data of a particular object, so it can no
      longer be a static member function.  <para>
      -->
      <para>
	La función <function>print()</function> se ha modificado para
	imprimir en la salida un mensaje, el identificador del objeto
	y el contador de objetos. Como ahora accede al atributo
	<varname>name</varname> de un objeto concreto, ya no
	puede ser un método estático.
      </para>


      <!-- Inside main(), you can see that a second call to f() has
      been added. However, this call uses the common C approach of
      ignoring the return value. But now that you know how the value
      is returned (that is, code inside the function handles the
      return process, putting the result in a destination whose
      address is passed as a hidden argument), you might wonder what
      happens when the return value is ignored. The output of the
      program will throw some illumination on this.  -->
      <para>
	Dentro de <function>main()</function> puede ver que hay una
	segunda llamada a <function>f()</function>. Sin embargo esta
	llamada utiliza la característica de C para ignorar el valor
	de retorno. Pero ahora que sabe cómo se retorna el valor (es
	decir, código <emphasis>dentro</emphasis> de la función que
	maneja el proceso de retorno poniendo el resultado en un lugar
	cuya dirección se pasa como un argumento escondido), podría
	preguntarse qué ocurre cuando se ignora el valor de
	retorno. La salida del programa mostrará alguna luz sobre el
	asunto.
      </para>

      <!-- Before showing the output, here's a little program that
      uses iostreams to add line numbers to any file: -->
      <para>
	Pero antes de mostrar la salida, he aquí un pequeño programa
	que utiliza <classname>iostreams</classname> para añadir
	números de línea a cualquier archivo:
      </para>


//: V1C11:Linenum.cpp

      <!--
      The entire file is read into a vector<string>, using the same code
      that you've seen earlier in the book. When printing the line numbers,
      we'd like all the lines to be aligned with each other, and this
      requires adjusting for the number of lines in the file so that the
      width allowed for the line numbers is consistent. We can easily
      determine the number of lines using vector::size(), but what we
      really need to know is whether there are more than 10 lines, 100
      lines, 1,000 lines, etc. If you take the logarithm, base 10, of the
      number of lines in the file, truncate it to an int and add one to the
      value, you'll find out the maximum width that your line count will be.
      -->
      <para>
	El archivo se pasa a un <type>vector&lt;string></type>,
	utilizando el mismo código fuente que ha visto
	anteriormente en este libro. Cuando se ponen los números de
	línea, nos gustaría que todas las líneas estuvieran alineadas,
	y esto necesita conocer el número de líneas en el archivo para
	que sea coherente.  Se puede conocer el número de líneas con
	<function>vector::size()</function>, pero lo que realmente
	necesitamos es conocer si hay más líneas de 10, 100, 1000,
	etc.  Si se utiliza el logaritmo en base 10 sobre el número de
	líneas en el archivo, se trunca a un entero y se añade uno al
	valor resultante, eso determinará el ancho máximo en dígitos
	que un número de línea puede tener.
      </para>

      <!-- You'll notice a couple of strange calls inside the for
	loop: setf() and width(). These are ostream calls that allow
	you to control, in this case, the justification and width of
	the output. However, they must be called each time a line is
	output and that is why they are inside the for loop. Volume 2
	of this book has an entire chapter explaining iostreams that
	will tell you more about these calls as well as other ways to
	control iostreams.  -->
      <para>
	Nótese que hay un par de llamadas extrañas dentro del bucle
	<kw>for</kw>: <function>setf()</function> y
	<function>width()</function>. Hay llamadas de
	<classname>ostream</classname> que permiten controlar, en este
	caso, la justificación y anchura de la salida. Sin embargo se
	debe llamar cada vez que se imprime línea y por eso están
	dentro del bucle <kw>for</kw>. El Volumen 2 de este libro
	tiene un capítulo entero que explica los
	<classname>iostreams</classname> y que cuenta más sobre estas
	llamadas así como otras formas de controlar los
	<classname>iostreams</classname>.  </para>

      <!-- When Linenum.cpp is applied to HowMany2.out, the result is
	-->
      <para>
	Cuando se aplica <filename>Linenum.cpp</filename> a
	<filename>HowMany2.out</filename>, resulta:
      </para>

<screen>
1) HowMany2()
2)   h: objectCount = 1
3) Entering f()
4) HowMany2(const HowMany2&amp;)
5)   h copy: objectCount = 2
6) x argument inside f()
7)   h copy: objectCount = 2
8) Returning from f()
9) HowMany2(const HowMany2&amp;)
10)   h copy copy: objectCount = 3
11) ~HowMany2()
12)   h copy: objectCount = 2
13) h2 after call to f()
14)   h copy copy: objectCount = 2
15) Call f(), no return value
16) HowMany2(const HowMany2&amp;)
17)   h copy: objectCount = 3
18) x argument inside f()
19)   h copy: objectCount = 3
20) Returning from f()
21) HowMany2(const HowMany2&amp;)
22)   h copy copy: objectCount = 4
23) ~HowMany2()
24)   h copy: objectCount = 3
25) ~HowMany2()
26)   h copy copy: objectCount = 2
27) After call to f()
28) ~HowMany2()
29)   h copy copy: objectCount = 1
30) ~HowMany2()
31)   h: objectCount = 0
</screen>

      <!--
      As you would expect, the first thing that happens is that the normal
      constructor is called for h, which increments the object count to
      one. But then, as f() is entered, the copy-constructor is quietly
      called by the compiler to perform the pass-by-value. A new object is
      created, which is the copy of h (thus the name "h copy") inside the
      function frame of f(), so the object count becomes two, courtesy of
      the copy-constructor.
      -->
      <para>
	Como se esperaba, la primera cosa que ocurre es que para
	<varname>h</varname> se llama al constructor normal, el cual
	incrementa el contador de objetos a uno. Pero entonces,
	mientras se entra en <function>f()</function>, el compilador
	llama silenciosamente al constructor de copia para hacer el
	paso por valor. Se crea un nuevo objeto, que es copia de
	<varname>h</varname> (y por tanto tendrá el identificador
	<quote>h copy</quote>) dentro del ámbito de la función
	<function>f()</function>.  Así pues, el contador de objetos se
	incrementa a dos, por cortesía del constructor de copia.
	</para>

      <!-- Line eight indicates the beginning of the return from
	f(). But before the local variable "h copy" can be destroyed
	(it goes out of scope at the end of the function), it must be
	copied into the return value, which happens to be h2. A
	previously unconstructed object (h2) is created from an
	existing object (the local variable inside f()), so of course
	the copy-constructor is used again in line nine. Now the name
	becomes "h copy copy" for h2's identifier because it's being
	copied from the copy that is the local object inside
	f(). After the object is returned, but before the function
	ends, the object count becomes temporarily three, but then the
	local object "h copy" is destroyed. After the call to f()
	completes in line 13, there are only two objects, h and h2,
	and you can see that h2 did indeed end up as "h copy copy."
	-->
      <para>
	La línea ocho indica el principio del retorno de
	<function>f()</function>. Pero antes de que se destruya la
	variable local <quote>h copy</quote> (pues sale de ámbito al
	final de la función), se debe copiar al valor de retorno, que
	es <varname>h2</varname>. Por tanto <varname>h2</varname>, que
	no estaba creado previamente, se crea de un objeto ya
	existente (la variable local dentro de
	<function>f()</function>) y el constructor de copia vuelve a
	utilizarse en la línea 9. Ahora el identificador de
	<varname>h2</varname> es <quote>h copy copy</quote> porque
	copió el identificador de la variable local de
	<function>f()</function>. Cuando se devuelve el objeto, pero
	antes de que la función termine, el contador de objetos se
	incrementa temporalmente a tres, pero la variable local con
	identificador <quote>h copy</quote> se destruye, disminuyendo
	a dos. Después de que se complete la llamada a
	<function>f()</function> en la línea 13, sólo hay dos objetos,
	<varname>h</varname> y <varname>h2</varname>, y puede
	comprobar, de hecho, que <varname>h2</varname> terminó con el
	identificador <quote>h copy copy</quote>.
      </para>

      <sect3>
	<!-- : Temporary objects -->
	<title>Objetos temporales</title>

	<!-- Line 15 begins the call to f(h), this time ignoring the
        return value. You can see in line 16 that the copy-constructor
        is called just as before to pass the argument in. And also, as
        before, line 21 shows the copy-constructor is called for the
        return value. But the copy-constructor must have an address to
        work on as its destination (a this pointer). Where does this
        address come from?  -->
	<para>
	  En la línea 15 se empieza la llamada a <code>f(h)</code>, y
	  esta vez ignora el valor de retorno. Puede ver que se invoca
	  el constructor de copia en la línea 16, igual que antes,
	  para pasar el argumento.  Y también, igual que antes, en la
	  línea 21 se llama al constructor de copia para el valor de
	  retorno. Pero el constructor de copia necesita una dirección
	  para utilizar como destino (es decir, para trabajar con el
	  puntero <kw>this</kw>). ¿De dónde procede esta dirección?
	</para>

	<!-- It turns out the compiler can create a temporary object
	  whenever it needs one to properly evaluate an expression. In
	  this case it creates one you don't even see to act as the
	  destination for the ignored return value of f(). The
	  lifetime of this temporary object is as short as possible so
	  the landscape doesn't get cluttered up with temporaries
	  waiting to be destroyed and taking up valuable resources. In
	  some cases, the temporary might immediately be passed to
	  another function, but in this case it isn't needed after the
	  function call, so as soon as the function call ends by
	  calling the destructor for the local object (lines 23 and
	  24), the temporary object is destroyed (lines 25 and 26).
	  -->
	<para>
	  Esto prueba que el compilador puede crear un objeto temporal
	  cuando lo necesita para evaluar adecuadamente una
	  expresión. En este caso, crea uno que ni siquiera se le ve
	  actuar como destino para el valor ignorado retornado por
	  <function>f()</function>. El tiempo de vida de este objeto
	  temporal es tan corto como sea posible para que el programa
	  no se llene de objetos temporales esperando a ser
	  destruidos, lo cual provocaría la utilización ineficaz de
	  recursos valiosos. En algunos casos, el objeto temporal
	  podría pasarse inmediatamente a otra función, pero en este
	  caso no se necesita después de la llamada a la función, así
	  que en cuanto la función termina, llamando al destructor del
	  objeto local (líneas 23 y 24), el objeto temporal también se
	  destruye (líneas 25 y 26).
	</para>

	<!--
	  Finally, in lines 28-31, the h2 object is destroyed,
	  followed by h, and the object count goes correctly back to
	  zero.  -->
	<para>
	  Finalmente, de la línea 28 a la línea 31, se destruye el
	  objeto <varname>h2</varname>, seguido de
	  <varname>h</varname> y el contador de objetos vuelve a cero.
	</para>
      </sect3>
    </sect2>

    <sect2>
      <!-- : Default copy-constructor -->
      <title>El constructor de copia por defecto</title>

      <!--
      Because the copy-constructor implements pass and return by value, it's
      important that the compiler creates one for you in the case of simple
      structures - effectively, the same thing it does in C. However, all
      you've seen so far is the default primitive behavior: a bitcopy.
      -->
      <para>
	Como el constructor de copia implementa el paso y retorno por
	valor, es importante que el compilador cree uno en el caso de
	estructuras simples (de hecho, es lo mismo que hace C). Sin
	embargo todo lo que se ha visto es el comportamiento por
	defecto: una copia bit a bit.
      </para>

      <!--
      When more complex types are involved, the C++ compiler will still
      automatically create a copy-constructor if you don't make one. Again,
      however, a bitcopy doesn't make sense, because it doesn't necessarily
      implement the proper meaning.
      -->
      <para>
	Cuando se utilizan tipos más complejos, el compilador de C++
	creará un constructor de copia automáticamente si no se implementa
	explícitamente. De nuevo, una copia bit a bit no tiene
	sentido, porque no tiene porqué ser el comportamiento que se
	necesita.
      </para>

      <!--
      Here's an example to show the more intelligent approach the compiler
      takes. Suppose you create a new class composed of objects of several
      existing classes. This is called, appropriately enough, composition,
      and it's one of the ways you can make new classes from existing
      classes. Now take the role of a naive user who's trying to solve a
      problem quickly by creating a new class this way. You don't know about
      copy-constructors, so you don't create one. The example demonstrates
      what the compiler does while creating the default copy-constructor for
      your new class:
      -->
      <para>
	He aquí un ejemplo para mostrar el comportamiento más
	inteligente del compilador. Suponga que crea una nueva clase
	compuesta por objetos de varias clases diferentes. A esto se le
	denomina <emphasis>composición</emphasis>, y es una de las
	formas en las que se pueden hacer nuevas clases a partir de las
	ya existentes. Ahora desempeñe el papel de un novato que trata
	de resolver un problema rápidamente creando una nueva clase de
	esta manera. No sabe nada sobre los constructores de copia, así
	que no lo implementa. El ejemplo muestra lo que el compilador
	hace cuando crea un constructor de copia por defecto para su nueva
	clase:
      </para>


//: V1C11:DefaultCopyConstructor.cpp

      <!--
      The class WithCC contains a copy-constructor, which simply announces
      that it has been called, and this brings up an interesting issue. In
      the class Composite, an object of WithCC is created using a default
      constructor. If there were no constructors at all in WithCC, the
      compiler would automatically create a default constructor, which would
      do nothing in this case. However, if you add a copy-constructor,
      you've told the compiler you're going to handle constructor creation,
      so it no longer creates a default constructor for you and will
      complain unless you explicitly create a default constructor as was
      done for WithCC.
      -->
      <para>
	La clase <classname>WithCC</classname> contiene un constructor
	de copia, que simplemente anuncia que ha sido llamado, y esto
	demuestra una cuestión interesante: dentro de la clase
	<classname>Composite</classname> se crea un objeto tipo
	<classname>WithCC</classname> utilizando el constructor por
	defecto. Si <classname>WithCC</classname> no tuviera ningún
	constructor, el compilador crearía uno por defecto
	automáticamente, el cual, en este caso, no haría nada. No
	obstante, si añade un constructor por defecto, le está
	diciendo al compilador que ha de utilizar los constructores
	disponibles, por lo que él no crea ningún constructor por
	defecto y se quejará a no ser que explícitamente cree un
	constructor por defecto, como se hizo en
	<classname>WithCC</classname>.
      </para>

      <!-- The class WoCC has no copy-constructor, but its constructor
      will store a message in an internal string that can be printed
      out using print( ). This constructor is explicitly called in
      Composite's constructor initializer list (briefly introduced in
      Chapter 8 and covered fully in Chapter 14). The reason for this
      becomes apparent later.  -->
      <para>
	La clase <classname>WoCC</classname> no tiene constructor de
	copia, pero su constructor almacenará un <type>string</type>
	interno imprimible por la función
	<function>print()</function>.  La lista de inicialización del
	constructor (presentado brevemente en el <link linkend="C08">
	Capítulo 8</link> y tratado completamente en el <link
	linkend="C14">Capítulo 14</link>) de
	<classname>Composite</classname> llama explícitamente a este
	constructor. La razón de esto se verá posteriormente.
	</para>

      <!--
      The class Composite has member objects of both
	WithCC and WoCC (note the embedded object wocc is initialized
	in the constructor-initializer list, as it must be), and no
	explicitly defined copy-constructor. However, in main() an
	object is created using the copy-constructor in the
	definition:
      -->
      <para>
	La clase <classname>Composite</classname> tiene objetos
	miembro tanto de <classname>WithCC</classname> como de
	<classname>WoCC</classname> (note que el objeto interno
	<varname>wocc</varname> se inicializa en la lista de
	inicializadores del constructor de
	<classname>Composite</classname>, como debe ser), pero no
	están inicializados explícitamente en el constructor de
	copia. Sin embargo un objeto <classname>Composite</classname> se
	crea en <function>main()</function> utilizando el constructor
	de copia:
      </para>

<programlisting>
Composite c2 = c;
</programlisting>

      <!--
      The copy-constructor for Composite is created automatically by the
      compiler, and the output of the program reveals the way that it is
      created:
      -->
      <para>
	El compilador ha creado un constructor de copia para
	<classname>Composite</classname> automáticamente, y la salida del
	programa revela la manera en que se crea:
      </para>

<programlisting>
Contents of c: Composite()
Calling Composite copy-constructor
WithCC(WithCC&amp;)
Contents of c2: Composite()
</programlisting>

      <!--
      To create a copy-constructor for a class that uses composition (and
      inheritance, which is introduced in Chapter 14), the compiler
      recursively calls the copy-constructors for all the member objects and
      base classes. That is, if the member object also contains another
      object, its copy-constructor is also called. So in this case, the
      compiler calls the copy-constructor for WithCC. The output shows this
      constructor being called. Because WoCC has no copy-constructor, the
      compiler creates one for it that just performs a bitcopy, and calls
      that inside the Composite copy-constructor. The call to
      Composite::print() in main shows that this happens because the
      contents of c2.wocc are identical to the contents of c.wocc. The
      process the compiler goes through to synthesize a copy-constructor is
      called memberwise initialization.
      -->
      <para>
	Para la creación de un constructor de copia para una clase que
	utiliza composición (y herencia, que se trata en el <link
	linkend="C14">Capítulo 14</link>), el compilador llama a todos
	los constructores de copia de todos los miembros objeto y de
	las clases base de manera recursiva. Es decir, si el miembro
	también contiene otro objeto, también se llama a su
	constructor de copia. En el ejemplo, el compilador llama al
	constructor de copia de <classname>WithCC</classname>. La
	salida muestra que se llama a este constructor. Como
	<classname>WoCC</classname> no tiene constructor de copia, el
	compilador crea uno que realiza simplemente una copia bit a
	bit para que el constructor de copia de
	<classname>Composite</classname> lo pueda llamar. La llamada a
	<code>Composite::print()</code> en <function>main()</function>
	muestra que esto ocurre, porque el contenido de
	<varname>c2.wocc</varname> es idéntico al contenido de
	<varname>c.wocc</varname>. El proceso que realiza el
	compilador para crear un constructor de copia se denomina
	<emphasis>inicialización de miembros</emphasis>
	(<foreignphrase>memberwise initialization</foreignphrase>).
	</para>

      <!-- It's always best to create your own copy-constructor
	instead of letting the compiler do it for you. This guarantees
	that it will be under your control.  -->
      <para>
	Se recomienda definir constructor de copia propio en vez de
	usar el que crea el compilador. Eso garantiza que estará bajo
	su control.
      </para>
    </sect2>

    <sect2>
      <!-- : Alternatives to copy-construction -->
      <title>Alternativas a la construcción por copia</title>
      <!--
      At this point your head may be swimming, and you might be wondering
      how you could have possibly written a working class without knowing
      about the copy-constructor. But remember: You need a copy-constructor
      only if you're going to pass an object of your class by value. If that
      never happens, you don't need a copy-constructor.
      -->
      <para>
	A estas alturas su cabeza debe estar echando humo, y se
	preguntará cómo es posible que pudiera escribir una clase que
	funcionase sin saber nada acerca del constructor de copia. No
	obstante, recuerde que el constructor de copia sólo es necesario
	cuando la clase se pasa <emphasis>por valor</emphasis>. Si esto
	no va a ocurrir, entonces no lo necesita.
      </para>

      <sect3>
	<!-- : Preventing pass-by-value -->
	<title>Evitando el paso por valor</title>

        <!--
        "But," you say, "if I don't make a copy-constructor, the compiler will
        create one for me. So how do I know that an object will never be
        passed by value?"
        -->
	<para>
	  <quote>Pero</quote>, puede decir, <quote>si no defino el
	  constructor de copia, el compilador lo creará por mí. ¿Cómo
	  sé que un objeto nunca se pasará por valor?</quote>
	  </para>

	<!-- There's a simple technique for preventing pass-by-value:
	  declare a private copy-constructor. You don't even need to
	  create a definition, unless one of your member functions or
	  a friend function needs to perform a pass-by-value. If the
	  user tries to pass or return the object by value, the
	  compiler will produce an error message because the
	  copy-constructor is private. It can no longer create a
	  default copy-constructor because you've explicitly stated
	  that you're taking over that job.  -->
	<para>
	  Existe una técnica simple para evitar el paso por valor:
	  declare un constructor de copia <kw>private</kw>.  Ni
	  siquiera necesita definirlo (sólo declararlo), a no ser que
	  un método o una función <kw>friend</kw> necesite realizar un
	  paso por valor. Si el usuario intenta pasar o retornar el
	  objeto por valor, el compilador se quejará con un error
	  porque el constructor de copia es privado. El compilador ya
	  no puede crear un constructor de copia por defecto porque
	  explícitamente ya hay uno creado.  </para>

	<!-- Here's an example: -->
	<para>
	  He aquí un ejemplo:
	</para>


//: V1C11:NoCopyConstruction.cpp

        <!-- Notice the use of the more general form -->
	<para>
	  Note la  utilización de la forma más general
	</para>


<programlisting>
NoCC(const NoCC&amp;);
</programlisting>

        <!-- using the const. -->
	<para>
	  utilizando <kw>const</kw>
	</para>
      </sect3>

      <sect3>
        <!-- : Functions that modify outside objects -->
	<title>Funciones que modifican objetos externos</title>

	<!-- Reference syntax is nicer to use than pointer syntax, yet
        it clouds the meaning for the reader. For example, in the
        iostreams library one overloaded version of the get() function
        takes a char& as an argument, and the whole point of the
        function is to modify its argument by inserting the result of
        the get(). However, when you read code using this function
        it's not immediately obvious to you that the outside object is
        being modified: -->
	<para>
	  La sintaxis de referencias es más agradable que la de
	  punteros, aunque oculte significado al que lea el código
	  fuente. Por ejemplo, en la librería
	  <filename>iostreams</filename> existe una versión
	  sobrecargada de la función <function>get()</function> que
	  tiene como argumento un <code>char &amp;</code>, y su
	  cometido es modificar ese argumento y utilizarlo como el
	  valor que retorna <function>get()</function>. No obstante,
	  si lee el código fuente de esta función, no es
	  inmediatamente obvio que la variable que se pasa como
	  argumento vaya a ser modificada:
	</para>


<programlisting>
char c;
cin.get(c);
</programlisting>


        <!--
        Instead, the function call looks like a pass-by-value, which suggests
        the outside object is not modified.
        -->
	<para>
	  Parece que a la función se le pasa por valor, lo que sugiere
	  que el argumento que se pasa <emphasis>no</emphasis> se
	  modifica.
	</para>

	<!-- Because of this, it's probably safer from a code
        maintenance standpoint to use pointers when you're passing the
        address of an argument to modify. If you always pass addresses
        as const references except when you intend to modify the
        outside object via the address, where you pass by non-const
        pointer, then your code is far easier for the reader to
        follow.  -->
	<para>
	  A causa de esto, es probablemente más seguro, desde el punto
	  de vista de mantenimiento del código fuente, utilizar punteros
	  que pasen la dirección del argumento que se desee
	  modificar. Si <emphasis>siempre</emphasis> pasa direcciones
	  como referencias constantes <emphasis>excepto</emphasis>
	  cuando intenta modificar el argumento que se pasa a través de
	  la dirección, donde pasaría un puntero no constante, entonces
	  es más fácil para el lector seguir el código fuente.
	</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <!-- : Pointers to members -->
    <title>Punteros a miembros</title>

    <!-- A pointer is a variable that holds the address of some
    location. You can change what a pointer selects at runtime, and
    the destination of the pointer can be either data or a
    function. The C++ pointer-to-member follows this same concept,
    except that what it selects is a location inside a class. The
    dilemma here is that a pointer needs an address, but there is no
    "address" inside a class; selecting a member of a class means
    offsetting into that class. You can't produce an actual address
    until you combine that offset with the starting address of a
    particular object. The syntax of pointers to members requires that
    you select an object at the same time you're dereferencing the
    pointer to member.  -->
    <para>
      Un puntero es una variable que contiene la dirección de alguna
      ubicación. Se puede cambiar a lo que el puntero apunta en tiempo
      de ejecución. La ubicación a la que apunta puede ser un dato o
      función. El <emphasis>puntero a miembro</emphasis> de C++ sigue
      el mismo concepto, excepto que a lo que apunta es una ubicación
      dentro de una clase. Pero surge el dilema de que un puntero
      necesita una dirección, pero no hay <quote>dirección</quote>
      alguna dentro de una clase; La selección de un miembro de una
      clase se realiza mediante un desplazamiento dentro de la
      clase. Pero primero hay que conocer la dirección donde comienza
      un objeto en particular para luego sumarle el desplazamiento y
      así localizar el miembro de la clase. La sintaxis de los
      punteros a miembros requiere que usted seleccione un objeto al
      mismo tiempo que está accediendo al contenido del puntero al
      miembro.
    </para>

    <!-- To understand this syntax, consider a simple structure, with
      a pointer sp and an object so for this structure. You can select
      members with the syntax shown: -->
    <para>
      Para entender esta sintaxis, considere una estructura simple,
      con un puntero <varname>sp</varname> y un objeto
      <varname>so</varname>.  Puede seleccionar sus miembros de la
      misma manera que en el siguiente ejemplo:
    </para>


//: V1C11:SimpleStructure.cpp


    <!--
    Now suppose you have an ordinary pointer to an integer, ip. To access
    what ip is pointing to, you dereference the pointer with a '*':
    -->
    <para>
      Ahora suponga que tiene un puntero normal que se llama
      <varname>ip</varname> y que apunta a un entero. Para acceder a
      lo que apunta <varname>ip</varname>, ha de estar precedido por
      un '*':
    </para>


<programlisting>
*ip=4;
</programlisting>


    <!--
    Finally, consider what happens if you have a pointer that happens to
    point to something inside a class object, even if it does in fact
    represent an offset into the object. To access what it's pointing at,
    you must dereference it with *. But it's an offset into an object, so
    you must also refer to that particular object. Thus, the * is combined
    with the object dereference. So the new syntax becomes ->* for a
    pointer to an object, and .* for the object or a reference, like this:
    -->
    <para>
      Finalmente, se preguntará qué pasa si tiene un puntero que está
      apuntando a algo que está dentro de un objeto, incluso si lo que
      realmente representa es un desplazamiento dentro del objeto. Para
      acceder a lo que está apuntando, debe preceder el puntero con '*'.
      Pero como es un desplazamiento dentro de un objeto, también ha de
      referirse al objeto con el que estamos tratando. Así, el * se
      combina con el objeto. Por tanto, la nueva sintaxis se escribe
      <emphasis>->*</emphasis> para un puntero que apunta a un objeto, y
      <emphasis>.*</emphasis> para un objeto o referencia, tal como
      esto:
    </para>

<programlisting>
objectPointer->*pointerToMember = 47;
object.*pointerToMember = 47;
</programlisting>


    <!--
    Now, what is the syntax for defining pointerToMember? Like any
    pointer, you have to say what type it's pointing at, and you use a *
    in the definition. The only difference is that you must say what class
    of objects this pointer-to-member is used with. Of course, this is
    accomplished with the name of the class and the scope resolution
    operator. Thus,
    -->
    <para>
      Pero, ¿cuál es la sintaxis para definir el
      <varname>pointerToMember</varname>? Pues como cualquier puntero,
      tiene que decir el tipo al que apuntará, por lo que se
      utilizaría el '*' en la definición. La única diferencia es que
      debe decir a qué clase de objetos apuntará ese atributo
      puntero. Obviamente, esto se consigue con el nombre de la clase
      y el operador de resolución de ámbito. Así,
    </para>

<programlisting>
int ObjectClass::*pointerToMember;
</programlisting>


    <!--
    defines a pointer-to-member variable called pointerToMember that
    points to any int inside ObjectClass. You can also initialize the
    pointer-to-member when you define it (or at any other time):
    -->
    <para>
      define un atributo puntero llamado
      <varname>pointerToMember</varname> que apunta a cualquier entero
      dentro de <classname>ObjectClass</classname>. También puede
      inicializar el puntero cuando lo defina (o en cualquier otro
      momento):
    </para>

<programlisting>
int ObjectClass::*pointerToMember = &amp;ObjectClass::a;
</programlisting>


    <!--
    There is actually no "address" of ObjectClass::a because you're just
    referring to the class and not an object of that class. Thus,
    &ObjectClass::a can be used only as pointer-to-member syntax.
    -->
    <para>
      Realmente no existe una <quote>dirección</quote> de
      <code>ObjectClass::a</code> porque se está refiriendo a la clase
      y no a un objeto de esa clase.  Así,
      <code>&amp;ObjectClass::a</code> se puede utilizar sólo con la
      sintaxis de un puntero a miembro.  </para>

    <!-- Here's an example that shows how to create and use pointers
      to data members: -->
    <para>
      He aquí un ejemplo que muestra cómo crear y utilizar punteros a
      atributos:
    </para>


//: V1C11:PointerToMemberData.cpp


    <!--
    Obviously, these are too awkward to use anywhere except for special
    cases (which is exactly what they were intended for).
    -->
    <para>
      Obviamente, son muy desagradables de utilizar en cualquier lugar
      excepto para caso especiales (que es exactamente para lo que se
      crearon).
    </para>


    <!--
    Also, pointers to members are quite limited: they can be assigned only
    to a specific location inside a class. You could not, for example,
    increment or compare them as you can with ordinary pointers.
    -->
    <para>
      Además, los punteros a miembro son bastante limitados: pueden
      asignarse solamente a una ubicación específica dentro de una
      clase.  No podría, por ejemplo, incrementarlos o compararlos tal
      como puede hacer con punteros normales.
    </para>


    <sect2>
      <!-- : Functions -->
      <title>Funciones</title>

      <!--
      A similar exercise produces the pointer-to-member syntax for member
      functions. A pointer to a function (introduced at the end of Chapter
      3) is defined like this:
      -->
      <para>
	Un ejercicio similar se produce con la sintaxis de puntero a
	miembro para métodos. Un puntero a una función (presentado al
	final del <link linkend="C03-punteros-a-funcion">Capítulo
	3</link>) se define como:
      </para>


<programlisting>
int (*fp)(float);
</programlisting>


      <!--
      The parentheses around (*fp) are necessary to force the compiler to
      evaluate the definition properly. Without them this would appear to be
      a function that returns an int*.
      -->
      <para>
	Los paréntesis que engloban a <code>(*fb)</code> son
	necesarios para que fuercen la evaluación de la definición
	apropiadamente. Sin ellos sería una función que devuelve un
	<type>int*</type>.
      </para>

      <!-- Parentheses also play an important role when defining and
	using pointers to member functions. If you have a function
	inside a class, you define a pointer to that member function
	by inserting the class name and scope resolution operator into
	an ordinary function pointer definition: -->
      <para>
	Los paréntesis también desempeñan un papel importante cuando se
	definen y utilizan punteros a métodos. Si tiene una función
	dentro de una clase, puede definir un puntero a ese método
	insertando el nombre de la clase y el operador de resolución de
	ámbito en una definición habitual de puntero a función:
      </para>


//: V1C11:PmemFunDefinition.cpp


      <!--
      In the definition for fp2 you can see that a pointer to member
      function can also be initialized when it is created, or at any other
      time. Unlike non-member functions, the & is not optional when taking
      the address of a member function. However, you can give the function
      identifier without an argument list, because overload resolution can
      be determined by the type of the pointer to member.
      -->
      <para>
	En la definición de <varname>fp2</varname> puede verse que el
	puntero a un método puede inicializarse cuando se crea, o en
	cualquier otro momento. A diferencia de las funciones no son
	miembros, el <literal>&amp;</literal> <emphasis>no</emphasis>
	es opcional para obtener la dirección de un método. Sin
	embargo, se puede dar el identificador de la función sin la
	lista de argumentos, porque la sobrecarga se resuelve por el
	tipo de puntero a miembro.
      </para>

      <sect3>
	<!-- : An example -->
	<title>Un ejemplo</title>

        <!-- The value of a pointer is that you can change what it
        points to at runtime, which provides an important flexibility
        in your programming because through a pointer you can select
        or change behavior at runtime. A pointer-to-member is no
        different; it allows you to choose a member at
        runtime. Typically, your classes will only have member
        functions publicly visible (data members are usually
        considered part of the underlying implementation), so the
        following example selects member functions at runtime.  -->
	<para>
	  Lo interesante de un puntero es que se puede cambiar el
	  valor del mismo para apuntar a otro lugar en tiempo de
	  ejecución, lo cual proporciona mucha flexibilidad en la
	  programación porque a través de un puntero se puede cambiar
	  el <emphasis>comportamiento</emphasis> del programa en
	  tiempo de ejecución. Un puntero a miembro no es distinto; le
	  permite elegir un miembro en tiempo de
	  ejecución. Típicamente, sus clases sólo tendrán métodos
	  visibles públicamente (los atributos normalmente se
	  consideran parte de la implementación que va oculta), de
	  modo que el siguiente ejemplo elige métodos en tiempo de
	  ejecución.
	</para>


//: V1C11:PointerToMemberFunction.cpp


        <!--
        Of course, it isn't particularly reasonable to expect the casual user
        to create such complicated expressions. If the user must directly
        manipulate a pointer-to-member, then a typedef is in order. To really
        clean things up, you can use the pointer-to-member as part of the
        internal implementation mechanism. Here's the preceding example using
        a pointer-to-member inside the class. All the user needs to do is pass
        a number in to select a function.[48]
        -->
	<para>
	  Por supuesto, no es razonable esperar que el usuario casual
	  cree expresiones tan complejas. Si el usuario necesita
	  manipular directamente un puntero a miembro, los
	  <kw>typedef</kw> vienen al rescate. Para dejar aún mejor las
	  cosas, puede utilizar un puntero a función como parte del
	  mecanismo interno de la implementación. He aquí un ejemplo
	  que utiliza un puntero a miembro <emphasis>dentro</emphasis>
	  de la clase. Todo lo que el usuario necesita es pasar un
	  número para elegir una función.
	  <footnote><para>Gracias a Owen Mortensen por este ejemplo</para></footnote>
	</para>


//: V1C11:PointerToMemberFunction2.cpp


        <!--
        In the class interface and in main(), you can see that the entire
        implementation, including the functions, has been hidden away. The
        code must even ask for the count() of functions. This way, the class
        implementer can change the quantity of functions in the underlying
        implementation without affecting the code where the class is used.
        -->
	<para>
	  En la interfaz de la clase y en <function>main()</function>,
	  puede observar que toda la implementación, funciones
	  incluidas, es privada. El código ha de pedir el
	  <function>count()</function> de las funciones. De esta
	  manera, el que implementa la clase puede cambiar la cantidad
	  de funciones en la implementación por debajo sin que afecte
	  al código que utilice la clase.
	</para>

	<!-- The initialization of the pointers-to-members in the
	  constructor may seem overspecified. Shouldn't you be able to
	  say -->
	<para>
	  La inicialización de los punteros a miembro en el
	  constructor puede parecer redundante. ¿No debería ser capaz
	  de poner
	</para>


<programlisting>
fptr[1] = &amp;g;
</programlisting>


        <!--
        because the name g occurs in the member function, which is
        automatically in the scope of the class? The problem is this doesn't
        conform to the pointer-to-member syntax, which is required so
        everyone, especially the compiler, can figure out what's going
        on. Similarly, when the pointer-to-member is dereferenced, it seems
        like
        -->
	<para>
	  porque el nombre <varname>g</varname> es un método, el cual
	  está en el ámbito de la clase? El problema aquí es que no
	  sería conforme a la sintaxis de puntero a miembro.  Así todo
	  el mundo, incluido el compilador, puede imaginarse qué está
	  pasando.  De igual forma, cuando se accede al contenido del
	  puntero a miembro, parece que
	</para>


<programlisting>
(this->*fptr[i])(j);
</programlisting>


        <!--
        is also over-specified; this looks redundant. Again, the syntax
        requires that a pointer-to-member always be bound to an object when it
        is dereferenced.
        -->
	<para>
	  también es redundante; <kw>this</kw> parece redundante. La
	  sintaxis necesita que un puntero a miembro siempre esté
	  ligado a un objeto cuando se accede al contenido al que
	  apunta.
	</para>
      </sect3>
    </sect2>
  </sect1>

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

    <!-- Pointers in C++ are almost identical to pointers in C, which
    is good. Otherwise, a lot of C code wouldn't compile properly
    under C++. The only compile-time errors you will produce occur
    with dangerous assignments. If these are in fact what are
    intended, the compile-time errors can be removed with a simple
    (and explicit!) cast.  -->
    <para>
      Los punteros en C++ son casi idénticos a los punteros en C, lo
      cual es bueno. De otra manera, gran cantidad de código C no
      compilaría en C++. Los únicos errores en tiempo de compilación
      serán aquéllos que realicen asignaciones peligrosas. Esos
      errores pueden eliminarse con una simple (pero explícito!)
      molde.
    </para>


    <!--
    C++ also adds the reference from Algol and Pascal, which is like a
    constant pointer that is automatically dereferenced by the compiler. A
    reference holds an address, but you treat it like an
    object. References are essential for clean syntax with operator
    overloading (the subject of the next chapter), but they also add
    syntactic convenience for passing and returning objects for ordinary
    functions.
    -->
    <para>
      C++ también añade la <emphasis>referencia</emphasis> de Algol y
      Pascal, que es como un puntero constante que el compilador hace
      que se acceda directamente al contenido al que apunta. Una
      referencia contiene una dirección, pero se trata como un
      objeto. Las referencias son esenciales para una sintaxis clara con
      la sobrecarga de operadores (el tema del siguiente capítulo), pero
      también proporcionan mejoras sintácticas para el paso y retorno de
      objetos en funciones normales.
    </para>

    <!-- The copy-constructor takes a reference to an existing object
    of the same type as its argument, and it is used to create a new
    object from an existing one. The compiler automatically calls the
    copy-constructor when you pass or return an object by
    value. Although the compiler will automatically create a
    copy-constructor for you, if you think one will be needed for your
    class, you should always define it yourself to ensure that the
    proper behavior occurs. If you don't want the object passed or
    returned by value, you should create a private copy-constructor.
    -->
    <para>
      El constructor de copia coge una referencia a un objeto
      existente del mismo tipo que el argumento, y lo utiliza para la
      creación de un nuevo objeto a partir del que existente. El
      compilador llama automáticamente al constructor de copia cuando
      pasa o retorna un objeto por valor. Aunque el compilador crea un
      constructor de copia automáticamente, si cree que su clase
      necesita uno, debería definirlo para asegurar un comportamiento
      apropiado. Si no desea que el objeto se pase o retorne por
      valor, debería crear un constructor de copia privado.
      </para>

    <!-- Pointers-to-members have the same functionality as ordinary
      pointers: You can choose a particular region of storage (data or
      function) at runtime. Pointers-to-members just happen to work
      with class members instead of with global data or functions. You
      get the programming flexibility that allows you to change
      behavior at runtime.  -->
    <para>
      Los punteros a miembro tienen la misma capacidad que los
      punteros normales: puede elegir una región de memoria particular
      (atributo o método) en tiempo de ejecución. Los punteros a
      miembro funcionan con los miembros de una clase en vez de
      variables o funciones globales.  Ofrecen la suficiente
      flexibilidad para cambiar el comportamiento en tiempo de
      ejecución.
    </para>
  </sect1>

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

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

    <orderedlist>
      <listitem>
	<!-- 1. Turn the "bird & rock" code fragment at the beginning
	of this chapter into a C program (using structs for the data
	types), and show that it compiles. Now try to compile it with
	the C++ compiler and see what happens.  -->
	<para>
	  Convierta el fragmento de código <quote>bird &amp;
	    rock</quote> del principio de este capítulo a un programa
	    C (utilizando estructuras para los tipos de datos), y que
	    compile.  Ahora intente compilarlo con un compilador de
	    C++ y vea qué ocurre.
	</para>
	</listitem>

      <listitem>
	<!-- 2. Take the code fragments in the beginning of the
	section titled "References in C++" and put them into a
	main(). Add statements to print output so that you can prove
	to yourself that references are like pointers that are
	automatically dereferenced.  -->
	  <para>
	    Coja los fragmentos de código al principio de la sección
	  titulada <quote>Referencias en C++</quote> y póngalos en un
	  <function>main()</function>.  Añada sentencias para imprimir
	  en la salida para que pueda demostrar usted mismo que las
	  referencias son como punteros que se dereferencian
	  automáticamente.
	</para>
      </listitem>

      <listitem>
	<!-- 3. Write a program in which you try to (1) Create a
	reference that is not initialized when it is created. (2)
	Change a reference to refer to another object after it is
	initialized. (3) Create a NULL reference.  -->
	<para>
	  Escriba un programa en el cual intente (1) Crear una
	  referencia que no esté inicializada cuando se crea. (2)
	  Cambiar una referencia para que se refiera a otro objeto
	  después de que se haya inicializado. (3) Crear una
	  referencia nula.
	  </para>
      </listitem>

      <listitem>
	<!-- 4. Write a function that takes a pointer argument,
	modifies what the pointer points to, and then returns the
	destination of the pointer as a reference.  -->
	<para>
	  Escriba una función que tome un puntero por argumento,
	  modifique el contenido de lo que el apunta puntero, y
	  retorne ese mismo contenido como si de una referencia se
	  tratara.
	</para>
      </listitem>

	<listitem>
	<!-- 5. Create a class with some member functions, and make
	that the object that is pointed to by the argument of Exercise
	4. Make the pointer a const and make some of the member
	functions const and prove that you can only call the const
	member functions inside your function. Make the argument to
	your function a reference instead of a pointer.  -->
	<para>
	  Cree una nueva clase con algunos métodos, y haga que el
	  objeto sea apuntado por el argumento del Ejercicio 4. Haga
	  que el puntero pasado como argumento y algunos métodos sean
	  constantes y pruebe que sólo puede llamar a los métodos
	  constantes dentro de su función. Haga que el argumento de su
	  función sea una referencia en vez de un puntero.
	</para>
      </listitem>

	<listitem>
	<!--
	6. Take the code fragments at the beginning of the section titled
	"Pointer references" and turn them into a program.
	-->
	<para>
	  Coja los fragmentos de código al principio de la sección
	  <quote>referencias a puntero</quote> y conviértalos en un
	  programa.
	</para>
      </listitem>

      <listitem>
	<!-- 7. Create a function that takes an argument of a
	reference to a pointer to a pointer and modifies that
	argument. In main(), call the function.  -->
	<para>
	  Cree una función que tome como argumento una referencia a
	  un puntero que apunta a otro puntero y modifique ese argumento. En
	  <function>main()</function>, llame a la función.
	</para>
      </listitem>

      <listitem>
	<!-- 8. Create a function that takes a char& argument and
	modifies that argument. In main(), print out a char variable,
	call your function for that variable, and print it out again
	to prove to yourself that it has been changed. How does this
	affect program readability?  -->
	<para>
	  Cree una función que toma un argumento del tipo
	  <type>char&amp;</type> y lo modifica. En el
	  <function>main()</function> imprima a la salida una variable
	  <type>char</type>, llame a su función con esa variable e
	  imprima la variable de nuevo para demostrar que ha sido cambiada.
	  ¿Cómo afecta esto a la legibilidad del programa?
	</para>
      </listitem>

      <listitem>
	<!-- 9. Write a class that has a const member function and a
	non-const member function. Write three functions that take an
	object of that class as an argument; the first takes it by
	value, the second by reference, and the third by const
	reference. Inside the functions, try to call both member
	functions of your class and explain the results.  -->
	<para>
	  Escriba una clase que tiene un método constante y otra que
	  no lo tiene. Escriba tres funciones que toman un objeto de
	  esa clase como argumento; la primera lo toma por valor, la
	  segunda lo toma por referencia y la tercera lo toma mediante
	  una referencia constante. Dentro de las funciones, intente
	  llamar a las dos funciones de su clase y explique los
	  resultados.
	</para>
      </listitem>

	<listitem>
	<!-- 10. (Somewhat challenging) Write a simple function that
	takes an int as an argument, increments the value, and returns
	it. In main(), call your function. Now discover how your
	compiler generates assembly code and trace through the
	assembly statements so that you understand how arguments are
	passed and returned, and how local variables are indexed off
	the stack.  -->
	  <para>
	    (Algo difícil) Escriba una función simple que toma un
	    entero como argumento, incrementa el valor, y lo retorna. En
	    <function>main()</function>, llame a su función. Intente que el
	    compilador genere el código ensamblador e intente entender cómo
	    los argumentos se pasan y se retornan, y cómo las variables locales
	    se colocan en la pila.
	  </para>
	</listitem>

      <listitem>
	<!--
	11. Write a function that takes as its arguments a char, int, float,
	and double. Generate assembly code with your compiler and find the
	statements that push the arguments on the stack before a function
	call.
	-->
	<para>
	  Escriba una función que tome como argumentos un
	  <type>char</type>, <type>int</type>, <type>float</type> y
	  <type>double</type>. Genere el código ensamblador con su
	  compilador y busque las instrucciones que apilan los
	  argumentos en la pila antes de efectuar la llamada a
	  función.
	</para>
      </listitem>

      <listitem> <!-- 12. Write a function that returns a
	double. Generate assembly code and determine how the value is
	returned.  -->
	<para>
	  Escriba una función que devuelva un <type>double</type>.
	  Genere el código ensamblador y explique cómo se retorna el
	  valor.
	</para>
      </listitem>

      <listitem> <!-- 13. Produce assembly code for
	PassingBigStructures.cpp. Trace through and demystify the way
	your compiler generates code to pass and return large
	structures.  -->
	  <para>
	    Genere el código ensamblador de
	    <filename>PassingBigStructures.cpp</filename>. Recorra y
	    desmitifique la manera en que su compilador genera el
	    código para pasar y devolver estructuras grandes.
	  </para>
	</listitem>

	<listitem>
	<!-- 14. Write a simple recursive function that decrements its
	argument and returns zero if the argument becomes zero,
	otherwise it calls itself. Generate assembly code for this
	function and explain how the way that the assembly code is
	created by the compiler supports recursion.  -->
	<para>
	  Escriba una simple función recursiva que disminuya su
	  argumento y retorne cero si el argumento llega a cero, o
	  en otro caso que se llame a sí misma. Genere el código
	  ensamblador para esta función y explique la forma en el
	  compilador implementa la recurrencia.
	</para>
      </listitem>

      <listitem>
	<!-- 15. Write code to prove that the compiler automatically
	synthesizes a copy-constructor if you don't create one
	yourself. Prove that the synthesized copy-constructor performs
	a bitcopy of primitive types and calls the copy-constructor of
	user-defined types.  -->
	  <para>
	  Escriba código para demostrar que el compilador genera un
	  constructor de copia automáticamente en caso de que no lo
	  haga el programador. Demuestre que el constructor de copia
	  generado por el compilador realiza una copia bit a bit de
	  tipos primitivos y llama a los constructores de copia de los
	  tipos definidos por el usuario.
	</para>
      </listitem>

      <listitem> <!-- 16. Write a class with a copy-constructor that
	announces itself to cout. Now create a function that passes an
	object of your new class in by value and another one that
	creates a local object of your new class and returns it by
	value. Call these functions to prove to yourself that the
	copy-constructor is indeed quietly called when passing and
	returning objects by value.  -->
	<para>
	  Escriba una clase en la que el constructor de copia se
	  anuncia a sí mismo a través de
	  <varname>cout</varname>. Ahora cree una función que pasa un
	  objeto de su nueva clase por valor y otra más que crea un
	  objeto local de su nueva clase y lo devuelve por valor.
	  Llame a estas funciones para demostrar que el constructor de
	  copia es, en efecto, llamado cuando se pasan y retornan
	  objetos por valor.
	</para>
      </listitem>

	<listitem> <!-- 17. Create a class that contains a
	double*. The constructor initializes the double* by calling
	new double and assigning a value to the resulting storage from
	the constructor argument. The destructor prints the value
	that's pointed to, assigns that value to -1, calls delete for
	the storage, and then sets the pointer to zero. Now create a
	function that takes an object of your class by value, and call
	this function in main(). What happens? Fix the problem by
	writing a copy-constructor.  -->
	<para>
	  Cree un objeto que contenga un <type>double*</type>.  Que el
	  constructor inicialice el <type>double*</type> llamando a
	  <code>new double</code> y asignando un valor. Entonces, que
	  el destructor imprima el valor al que apunta, asigne ese
	  valor a -1, llame a <kw>delete</kw> para liberar la memoria
	  y ponga el puntero a cero. Ahora cree una función que tome
	  un objeto de su clase por valor, y llame a esta función
	  desde <function>main()</function>. ¿Qué ocurre?  Solucione
	  el problema escribiendo un constructor de copia.
	</para>
      </listitem>

      <listitem> <!-- 18. Create a class with a constructor that looks
	like a copy-constructor, but that has an extra argument with a
	default value. Show that this is still used as the
	copy-constructor.  -->
	<para>
	  Cree una clase con un constructor que parezca un constructor
	  de copia, pero que tenga un argumento adicional con un valor
	  por defecto. Muestre que a pesar de eso se utiliza como
	  constructor de copia.
	</para>
	</listitem>

	<listitem>
	<!-- 19. Create a class with a copy-constructor that announces
	itself. Make a second class containing a member object of the
	first class, but do not create a copy-constructor. Show that
	the synthesized copy-constructor in the second class
	automatically calls the copy-constructor of the first class.
	-->
	<para>
	  Cree una clase con un constructor de copia que se anuncie a
	  sí mismo (es decir que imprima por la salida que ha sido
	  llamado).  Haga una segunda clase que contenga un objeto
	  miembro de la primera clase, pero no cree un constructor de
	  copia. Demuestre que el constructor de copia, que genera
	  automáticamente el compilador en la segunda clase, llama al
	  constructor de copia de la primera.
	</para>
      </listitem>

      <listitem> <!-- 20. Create a very simple class, and a function
	that returns an object of that class by value. Create a second
	function that takes a reference to an object of your
	class. Call the first function as the argument of the second
	function, and demonstrate that the second function must use a
	const reference as its argument.  -->
	<para>
	  Cree una clase muy simple, y una función que devuelva un
	  objeto de esa clase por valor. Cree una segunda función que
	  tome una referencia de un objeto de su clase. Llame a la
	  segunda función pasándole como argumento una llamada a la
	  primera función, y demuestre que la segunda función debe
	  utilizar una referencia constante como argumento.
	</para>
      </listitem>

      <listitem> <!-- 21. Create a simple class without a
	copy-constructor, and a simple function that takes an object
	of that class by value. Now change your class by adding a
	private declaration (only) for the copy-constructor. Explain
	what happens when your function is compiled.  -->
	<para>
	  Cree una clase simple sin constructor de copia, y una
	  función simple que tome un objeto de esa clase por
	  valor. Ahora cambie su clase añadiéndole una declaración
	  (sólo declare, no defina) privada de un constructor de
	  copia. Explique lo que ocurre cuando compila la función.
	</para>
      </listitem>

      <listitem>
	<!-- 22. This exercise creates an alternative to using the
	copy-constructor. Create a class X and declare (but don't
	define) a private copy-constructor. Make a public clone()
	function as a const member function that returns a copy of the
	object that is created using new. Now write a function that
	takes as an argument a const X& and clones a local copy that
	can be modified. The drawback to this approach is that you are
	responsible for explicitly destroying the cloned object (using
	delete) when you're done with it.  -->
	<para>
	  Este ejercicio crea una alternativa a la utilización del
	  constructor de copia. Cree una clase
	  <classname>X</classname> y declare (pero no defina) un
	  constructor de copia privado. Haga una función
	  <function>clone()</function> pública como un método
	  constante que devuelve una copia del objeto creado
	  utilizando <kw>new</kw>. Ahora escriba una función que tome
	  como argumento un <type>const X&amp;</type> y clone una
	  copia local que puede modificarse. El inconveniente de esto
	  es que es el programador el responsable de destruir
	  explícitamente el objeto clonado (utilizando
	  <kw>delete</kw>) cuando haya terminado con él.
	</para>
      </listitem>

      <listitem>
	<!-- 23. Explain what's wrong with both Mem.cpp and
	MemTest.cpp from Chapter 7. Fix the problem.  -->
	<para>
	  Explique qué está mal en <filename>Mem.cpp</filename> y
	  <filename>MemTest.cpp</filename> del <link
	  linkend="C07">Capítulo 7</link>. Solucione el problema.
	</para>
      </listitem>

      <listitem>
	<!-- 24. Create a class containing a double and a print()
	function that prints the double. In main(), create pointers to
	members for both the data member and the function in your
	class. Create an object of your class and a pointer to that
	object, and manipulate both class elements via your pointers
	to members, using both the object and the pointer to the
	object.  -->
	<para>
	  Cree una clase que contenga un <type>double</type> y una
	  función <function>print()</function> que imprima el
	  <type>double</type>. Cree punteros a miembro tanto
	  para el atributo como al método de su clase. Cree un objeto
	  de su clase y un puntero a ese objeto, y manipule ambos
	  elementos de la clase a través de los punteros a miembro,
	  utilizando tanto el objeto como el puntero al objeto.
	</para>
      </listitem>

      <listitem>
	<!-- 25. Create a class containing an array of int. Can you
	index through this array using a pointer to member?  -->
	<para>
	  Cree una clase que contenga un array de enteros. ¿Puede
	  recorrer el array mediante un puntero a miembro?
	</para>
      </listitem>

      <listitem>
	<!-- 26. Modify PmemFunDefinition.cpp by adding an overloaded
	member function f() (you can determine the argument list that
	causes the overload). Now make a second pointer to member,
	assign it to the overloaded version of f(), and call the
	function through that pointer. How does the overload
	resolution happen in this case?  -->
	<para>
	  Modifique <filename>PmemFunDefinition.cpp</filename>
	  añadiendo un método <function>f()</function> sobrecargado
	  (puede determinar la lista de argumentos que cause la
	  sobrecarga).  Ahora cree un segundo puntero a miembro,
	  asígnelo a la versión sobrecargada de
	  <function>f()</function>, y llame al método a través del
	  puntero. ¿Cómo sucede la resolución de la función
	  sobrecargada en este caso?
	</para>
      </listitem>

      <listitem> <!-- 27. Start with FunctionTable.cpp from Chapter
	3. Create a class that contains a vector of pointers to
	functions, with add() and remove( ) member functions to add
	and remove pointers to functions. Add a run() function that
	moves through the vector and calls all of the functions.  -->
	<para>
	  Empiece con la función
	  <filename>FunctionTable.cpp</filename> del <link
	  linkend="C03">Capítulo 3</link>. Cree una clase que contenga
	  un <type>vector</type> de punteros a funciones, con métodos
	  <function>add()</function> y <function>remove()</function>
	  para añadir y quitar punteros a función. Añada una función
	  denominada <function>run()</function> que recorra el
	  <type>vector</type> y llame a todas la funciones.
	</para>
      </listitem>

      <listitem>
	<!-- Modify the above Exercise 27 so that it works with
	pointers to member functions instead. -->
	<para>
	  Modifique el Ejercicio 27 para que funcione con punteros a
	  métodos.
	</para>
      </listitem>
    </orderedlist>
  </sect1>
</chapter>