2010-01-27 13 views
6

En C++, un puntero es un puntero a una dirección de memoria donde se almacena otra variable y en C# una referencia es similar. ¿Cuál es la diferencia entre estos dos?Diferencia entre el puntero en C++ y el tipo de referencia en C#

+0

Acabo de leer lo que mejor se dice. ;-) http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx – Oliver

+0

Ver también http://stackoverflow.com/questions/430112/what- is-the-difference-between-ac-sharp-reference-and-a-pointer – nawfal

Respuesta

8

En C#, el tipo de referencia se recogerá automáticamente cuando ya no sea necesario.

0

La primera diferencia es que no puede usar la aritmética del puntero en las referencias. De lo contrario, son más o menos lo mismo.

  • Ambos apuntan/hacen referencia a un objeto real.
  • Tanto puede ser nulo/nulo (es decir, no apunta a un objeto válido)
  • Ambos se pueden asignar un nuevo objeto

Otra diferencia es que el recolector de basura se ocupa de los recursos asignados en C#. En C++, tiene que eliminarlos usted mismo (o usar un puntero inteligente).

Y luego, por supuesto ... no es necesario desreferencia referencias manualmente en C# para acceder al valor.

+0

oO ¿Por qué downvote? – Christian

+0

El downvote no es mío, pero hay una diferencia fundamental que se pasa por alto: el .NET Runtime mantiene como * absoluta invariante * que no se permite que exista referencia en ningún lugar del universo que desconozca, fuera de uno caso especial: las referencias se pueden marcar como "fijadas", y las referencias externas a los objetos fijados pueden existir a los objetos así marcados, pero tener un número significativo de pinchados a la vez tendrá efectos perjudiciales en el rendimiento del GC. – supercat

0

C++ es un puntero de nivel físico donde almacena el valor de la dirección física. La referencia de C# es más bien un puntero oculto u opaco en el que simplemente sabe que apunta a algún objeto.

En C++ usted trabaja con punteros ya sea en el nivel físico - operación de la memoria o que lo utiliza para acceder a los objetos a los que apunta.

// physical level operation 

// set pointer to specific address 
byte *pPointer = 0x00LB10; 
// increment pointer 
pPointer++; 

// OR 
// dereference operation for classes and structure 
pPointer->MyProperty 

En C# sólo se puede usar de referencia (tipo de referencia de objeto) para acceder a objetos.

MyReference.Property 
1

Las llamadas referencias en C# se implementan mediante un puntero a un puntero al objeto real. Se llaman manejadores y, aunque el manejador se mantiene fijo durante toda la vida útil del programa, el puntero interno cambia a medida que el recolector de elementos no utilizados mueve el objeto en la memoria durante la fase de compactación de la memoria.

+0

Si bien las diferentes implementaciones de .NET runtime y garbage-collector serían libres de hacer las cosas de manera diferente, las referencias en las implementaciones comunes de .NET con un recolector de basura stop-the-world son en realidad punteros directos.Cuando se ejecuta el GC, se visitará y actualizará cada referencia a un objeto que pueda moverse para reflejar la nueva ubicación del objeto. El código compilado tiene un metadato especial asociado con notación, para cada instrucción, qué registros contienen referencias en vivo, y el GC tiene la capacidad de actualizar los punteros almacenados en esos registros. – supercat

1

Esas son bestias diferentes. En C++, boost :: shared_ptr es algo similar a C# referenecs, pero también es una bestia distinta (de estos dos).

La referencia apunta a un objeto que será eliminado por un recolector de basura. Lo mismo sucede en caso de shared_ptr. Sin embargo, hay una diferencia conceptual entre la forma en que C# y boost :: shared_ptr siguen la vida útil de los objetos (ver a continuación).

Los punteros C++ pueden apuntar a cualquier cosa, asignada en pila (en cuyo caso, no es necesario deshacerse), estático en montón o algo asignado manualmente, bajo demanda, que luego debe liberarse y está totalmente en programador responsabilidad.

Diferencias entre shared_ptr y C# referencias:

shared_ptr es un contador de referencia. Cuenta cuántos clones de su puntero existen, y dispone el objeto si no hay ninguno. Esto no proporciona una solución contra referencias cruzadas (o referencias circulares) cuando A apunta a B, que apunta a A, pero tanto A como B ya no son necesarios.

La recolección de basura C# se ocupa de eso. C# no cuenta las referencias. En cambio, mantiene una lista de accesibilidad: a qué se puede acceder a través de todos los punteros abiertos que tenemos. Lo que no puede, está dispuesto. Este enfoque es más seguro, pero tiene varias desventajas en términos de previsibilidad de rendimiento.

8

Para mí, el concepto es el mismo, o al menos la intención de ser el mismo, pero el uso real dado, no es.

Cuando hablamos de punteros o referencia estamos hablando de un concepto. Esta variable "apunta a" o es una "referencia" a otra cosa, algo que está almacenado en otro lugar.

Si uso esa referencia, por ejemplo actualizando el valor, en realidad estoy actualizando el objeto al que se hace referencia, el objeto al que apunta la variable. Si tengo un objeto al que se hace referencia desde dos lugares diferentes, en realidad actualizo la misma cosa desde ambos lugares.

El concepto puede relacionarse con su dirección en el mundo real, es solo una forma de referirse a otra cosa, y esa referencia se puede compartir, como muchas personas que tienen mi dirección.

La diferencia está más en cómo se ha utilizado y qué está permitido por el idioma. Tenga en cuenta que los detalles de implementación de la referencia o puntero no están implícitos en el concepto en sí. En C# eso continúa siendo cierto.

Una referencia es una referencia y siendo así, solo no tiene sentido sumar dos referencias, o agregar una a una referencia ... ¿qué significa eso? No puedo agregar dos direcciones de inicio (como Baker Street + Home Street) ...

En C++, los detalles de implementación de la referencia son en realidad la referencia. De esta forma, un puntero no es solo un puntero, también es (y se utiliza como) una dirección de memoria. De esta forma, por ejemplo, puede agregar punteros, porque realmente tiene sentido agregar dos direcciones de memoria para obtener otra, o agregar 4 a una dirección de memoria. Así que en C++ un puntero dejó de ser un concepto y se convirtió en un nombre dado a un detalle de implementación real.

Es por eso que, en C#, los punteros y las referencias son cosas diferentes. Debido a que, semánticamente el significado es bastante similar, querían diferenciar del viejo concepto de C y C++, donde un puntero se convirtió en lo mismo que una dirección de memoria.

Te recomiendo que leas el artículo "References are not addresses" de Eric Lippert donde creo que hace un gran trabajo explicando las diferencias.

+2

No puede agregar dos punteros en C++. – fredoverflow

Cuestiones relacionadas