Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 235 — #273<br />
✐<br />
8.3. Argum<strong>en</strong>tos de funciones y valores de retorno<br />
const char* ccp = v(); // OK<br />
//! int* ip2 = w(); // Not OK<br />
const int* const ccip = w(); // OK<br />
const int* cip2 = w(); // OK<br />
//! *w() = 1; // Not OK<br />
} ///:~<br />
La función t() toma un puntero no-constante ordinario como argum<strong>en</strong>to, y u()<br />
toma un puntero constante. En el cuerpo de u() puede ver un int<strong>en</strong>to de modificar<br />
el valor de un puntero constante, algo incorrecto, pero puede copiar su valor <strong>en</strong> una<br />
variable no constante. El compilador también impide crear un puntero no constante<br />
y almac<strong>en</strong>ar <strong>en</strong> él la dirección cont<strong>en</strong>ida <strong>en</strong> un puntero constante.<br />
Las funciones v() y w() prueban las semánticas de retorno de valores. v() devuelve<br />
un const char* que se crea a partir de un literal de cad<strong>en</strong>a. Esta s<strong>en</strong>t<strong>en</strong>cia <strong>en</strong><br />
realidad g<strong>en</strong>era la dirección del literal una vez que el compilador lo crea y almac<strong>en</strong>a<br />
<strong>en</strong> área de almac<strong>en</strong>ami<strong>en</strong>to estática. Como se ha dicho antes, técnicam<strong>en</strong>te este<br />
vector de caracteres es una constante, como bi<strong>en</strong> indica el tipo de retorno de v().<br />
El valor de retorno de w() requiere que tanto el puntero como lo que apunta sean<br />
constantes. Como <strong>en</strong> v(), el valor devuelto por w() es valido una vez terminada la<br />
función solo porque es estático. Nunca debe devolver un puntero a una variable local<br />
pues se almac<strong>en</strong>an <strong>en</strong> la pila y al terminar la función los datos de la pila desaparec<strong>en</strong>.<br />
Lo que si puede hacer es devolver punteros que apuntan a datos almac<strong>en</strong>ados <strong>en</strong> el<br />
montón (heap), pues sigu<strong>en</strong> si<strong>en</strong>do validos después de terminar la función.<br />
En main() se prueban las funciones con varios argum<strong>en</strong>tos. Puede ver que t()<br />
aceptará como argum<strong>en</strong>to un puntero ordinario, pero si int<strong>en</strong>ta pasarle un puntero<br />
a una constante, no hay garantía de que no vaya a modificarse el valor de la variable<br />
apuntada; por ello el compilador lo indica con un m<strong>en</strong>saje de error. u() toma un<br />
puntero a constante, así que puede aceptar los dos tipos de argum<strong>en</strong>tos. Por eso una<br />
función que acepta un puntero a constante es más g<strong>en</strong>eral que una que acepta un<br />
puntero ordinario.<br />
Como es lógico, el valor de retorno de v() sólo se puede asignar a un puntero a<br />
constante. También era de esperar que el compilador rehuse asignar el valor devuelto<br />
por w() a un puntero ordinario, y que sí acepte un const int* const, pero podría<br />
sorpr<strong>en</strong>der un poco que también acepta un const int*, que no es exactam<strong>en</strong>te el tipo<br />
de retorno declarado <strong>en</strong> la función. De nuevo, como el valor (que es la dirección cont<strong>en</strong>ida<br />
<strong>en</strong> el puntero) se copia, el requisito de que la variable original permanezca<br />
inalterable se cumple automáticam<strong>en</strong>te. Por eso, el segundo const <strong>en</strong> la declaración<br />
const int* const sólo se aplica cuando lo use como recipi<strong>en</strong>te, <strong>en</strong> cuyo caso el<br />
compilador lo impediría.<br />
Criterio de paso de argum<strong>en</strong>tos<br />
En C es muy común el paso por valor, y cuando se quiere pasar una dirección<br />
la única posibilidad es usar un puntero 3 . Sin embargo, ninguno de estos modos es<br />
el preferido <strong>en</strong> <strong>C++</strong>. En su lugar, la primera opción cuando se pasa un parámetro<br />
es hacerlo por refer<strong>en</strong>cia o mejor aún, por refer<strong>en</strong>cia constante. Para el cli<strong>en</strong>te de la<br />
función, la sintaxis es idéntica que <strong>en</strong> el paso por valor, de ese modo no hay confusión<br />
posible con los punteros, no hay que p<strong>en</strong>sar <strong>en</strong> términos de punteros. Para<br />
3 Algunos autores dic<strong>en</strong> que todo <strong>en</strong> C se pasa por valor, ya que cuando se pasa un puntero se hace<br />
también una copia (de modo que el puntero se pasa por valor). En cualquier caso, hacer esta precisión<br />
puede, <strong>en</strong> realidad, confundir la cuestión.<br />
235<br />
✐<br />
✐<br />
✐<br />
✐