2010-10-13 12 views
11

Estaba estudiando referencias de punteros y encontré diferentes formas de introducir parámetros. ¿Alguien puede explicar lo que realmente significa cada uno?¿Cuándo es el momento adecuado para usar *, & o const en C++?

Creo que el primero es simple, es que x es una copia del parámetro ingresado para que se cree otra variable en la pila. En cuanto a los demás, no tengo ni idea.

void doSomething1(int x){ 
    //code 
} 
void doSomething2(int *x){ 
    //code 
} 

void doSomething3(int &x){ 
    //code 
} 
void doSomething3(int const &x){ 
    //code 
} 

También veo cosas como esta cuando se declaran las variables. No entiendo las diferencias entre ellos. Sé que el primero pondrá 100 en la variable y en la pila. No creará una nueva dirección ni nada.

//example 1 
int y = 100; 

//example 2 
int *y = 100; 

//Example 3: epic confusion! 
int *y = &z; 

Pregunta 1: ¿Cómo uso estos métodos? ¿Cuándo es más apropiado?

Pregunta 2: ¿Cuándo declaro las variables de esa manera?

Ejemplos serían geniales.

P.S. esta es una de las razones principales por las que no aprendí C++ ya que Java solo tiene recolección de basura. Pero ahora tengo que entrar en C++.

+2

Consulte [esta respuesta] (http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c/2139254#2139254) para ver algunas reglas generales sobre cómo pasar los parámetros a las funciones en C++. – sbi

+0

Buena discusión aquí: http: // stackoverflow.com/questions/2550377/when-pass-by-pointer-is-preferred-to-pass-by-reference-in-c/2550405 # 2550405 –

Respuesta

2

Lea S.Lippmann's C++ Premier o cualquier otro buen libro en C++. En cuanto a pasar los parámetros, generalmente cuando el copiado es barato pasamos por valor. Para parámetros de salida obligatorios usamos referencias, para parámetros de salida opcionales - punteros, para parámetros de entrada donde el copiado es costoso, pasamos por referencias const

0

El mejor momento para usar esos métodos es cuando es más eficiente pasar referencias que como opuestas a objetos enteros. A veces, algunas operaciones de estructura de datos también son más rápidas usando referencias (por ejemplo, insertarlas en una lista vinculada). La mejor manera de entender los indicadores es leer sobre ellos y luego escribir programas para usarlos (y compararlos con sus contrapartes de valor de paso).

Y para que conste, el conocimiento de los indicadores te hace considerablemente más valioso en el lugar de trabajo. (con demasiada frecuencia, los programadores de C++ son los "místicos" de la oficina, con conocimiento de cómo esas cajas mágicas debajo de los escritorios procesan código/semi-sarcasmo)

+0

No menciones acerca de "leer un libro". Ellos lo votaron a la baja: D: D: D –

+0

Bueno, entonces que así sea, sin embargo es la verdad. – SubSevn

+1

Sin duda lo es. Insisto en que C++ se estudie sistemáticamente. C++ es muy duro para "probar" algo y "Wow, woked => es correcto" –

4

partir de Scott Myers - más eficaz C++ -> 1

En primer lugar, reconocer que no hay tal cosa como una referencia nula. Una referencia siempre debe hacer referencia a algún objeto. Debido a que una referencia debe hacer referencia a un objeto, C++ requiere que las referencias se inicialicen.

Los apuntadores están sujetos a dicha restricción. El hecho de que no existe una referencia nula implica que puede ser más eficiente usar referencias que utilizar punteros. Eso es porque no hay necesidad de probar la validez de una referencia antes de usarla.

Otra diferencia importante entre los punteros y las referencias es que los punteros pueden reasignarse para referirse a objetos diferentes.Una referencia, sin embargo, siempre se refiere al objeto con el que se inicializa

En general, debe usar un puntero siempre que necesite tener en cuenta la posibilidad de que no haya nada a lo que hacer referencia (en cuyo caso puede configurar puntero a nulo) o siempre que necesite poder referirse a cosas diferentes en momentos diferentes (en cuyo caso puede cambiar el punto del puntero). Debe usar una referencia cada vez que sepa que siempre habrá un objeto al que referirse y también sabe que una vez que se está refiriendo a ese objeto, nunca querrá referirse a nada más.

Las referencias, entonces, son la característica preferida cuando sabe que tiene algo a lo que referirse, cuando nunca querrá referirse a nada más, y cuando implementa operadores cuyos requisitos sintácticos hacen que el uso de punteros sea indeseable. En todos los demás casos, adhiérase a los punteros.

1

vacío doSomething1 (int x) {// código } Éste pasa la variable por valor, lo que sucede dentro de la función, la variable original no cambia

vacío doSomething2 (int * x) { // código } Aquí pasa una variable de tipo puntero a entero. Así que cuando se accede a la cantidad que debe utilizar * x por el valor o X para la dirección de

vacío doSomething3 (int & x) {// código } Aquí es como la primera, pero pase lo que pase dentro de la función , la variable original también se cambiará

int y = 100; entero normal

// ejemplo 2 int * y = 100; puntero a dirección 100

// Ejemplo 3: confusión épica! int * y = & z; puntero a la dirección de z

1
void doSomething1(int x){ 
//code 
} 
void doSomething2(int *x){ 
//code 
} 

void doSomething3(int &x){ 
//code 
} 

y estoy realmente conseguir confundido entre ellos?

El primero es usar pass-by-value y el argumento de la función conservará su valor original después de la llamada.

Los dos últimos están utilizando pass-by-reference. Básicamente, son dos formas de lograr lo mismo. El argumento no está garantizado para conservar su valor original después de la llamada.

La mayoría de los programadores prefieren pasar objetos grandes por referencia constante para mejorar el rendimiento de su código y proporcionar una restricción de que el valor no cambiará. Esto asegura que el constructor de copia no se llame.

Su confusión puede deberse al operador '&' que tiene dos significados. El que parece familiarizado es el "operador de referencia". También se usa como el 'operador de dirección'. En el ejemplo que das, tomas la dirección de z.

Un buen libro para ver que cubre todo esto en detalle es 'Accelerated C++' de Andrew Koening.

10
//example 1 
int y = 100; 

//example 2 
int *y = 100; 

//Example 3: epic confusion! 
int *y = &z; 

Creo que el problema para la mayoría de los estudiantes es que en C++ tanto & y * tienen diferentes significados, dependiendo del contexto en el que se utilizan.
Si cualquiera de ellos aparece después de un tipo dentro de una declaración de objeto (T* o T&), son Modificadores de tipo de y cambiar el tipo de llanura T a una referencia a un T (T&) o un puntero a T (T*).
Si aparecen delante de un objeto (&obj o *obj), son operadores de prefijo unarios invocadas en el objeto. El prefijo & devuelve el dirección del objeto se invoca para, *desreferencias un puntero, iterador etc., produciendo el valor que hace referencia.

No ayuda a la confusión que los modificadores de tipo se apliquen al objeto que se declara, no al tipo. Es decir, T* a, b; define un llamado T*a y una llanura T llamado b, por lo que muchas personas prefieren escribir T *a, b; lugar (tenga en cuenta la colocación del tipo modificadores * adyacente que está definido el objeto, en lugar del tipo modificado).

También es inútil que el término "referencia" esté sobrecargado. Por un lado, significa una construcción sintáctica, como en T&. Pero también existe el significado más amplio de una "referencia" que es algo que se refiere a otra cosa. En este sentido, tanto un puntero T* como una referencia (otro significado T&) son referencias, en el sentido de que hacen referencia a algún objeto. Eso entra en juego cuando alguien dice que "un puntero hace referencia a algún objeto" o que un puntero es "desreferenciado".

Así que en sus casos específicos, # 1 define una llanura int, # 2 define un puntero a un int y lo inicializa con la dirección de 100 (lo vive allí es mejor dejar intacto), y # 3 define otro puntero y lo inicializa con la dirección de un objeto z (necesariamente un int, también).


A para cómo pasar objetos a las funciones en C++, here es una vieja respuesta de mi parte a eso.

+0

por lo que hace una gran diferencia cuando escribe * después de T o antes *. woah. – Pavan

+0

@Pavan: no se puede usar indistintamente, porque, dependiendo de si 'T' es el nombre de un tipo o un objeto, solo uno de ellos es válido. – sbi

+0

La pregunta ahora es si 'T & t;' está delante de un objeto o después de un tipo :) –

Cuestiones relacionadas