13.01.2015 Views

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

SHOW MORE
SHOW LESS

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 />

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!