2010-10-31 12 views
24

Quiero comprobar si dos referencias apuntan al mismo objeto. Parece que puedo simplemente usar¿Cómo debo comparar las referencias de Perl?

if ($ref1 == $ref2) { 
# cheap numeric compare of references 
print "refs 1 and 2 refer to the same thing\n"; 
} 

como se menciona en perlref, pero vagamente recuerdo haber visto el uso de alguna función para el mismo propósito. ¿Hay alguna razón por la que no deba usar la simple prueba de igualdad numérica?

Nota: solo quiero saber si las referencias apuntan exactamente al mismo objeto. No busco una manera de comparar el contenido del objeto (s).

Respuesta

23

referencias, por defecto, numify a sus direcciones. Esas direcciones de referencia son únicas para cada referencia, por lo que a menudo se pueden usar en las verificaciones de igualdad.

Sin embargo, en el fragmento que mostró, primero debe asegurarse de que tanto $ref1 como $ref2 son referencias reales. De lo contrario, podría obtener resultados incorrectos debido a escalares regulares que contienen direcciones de referencia.

Además, nada garantiza referencias para numerar a su dirección. Los objetos, por ejemplo, pueden usar la sobrecarga para influir en el valor que devuelven en diferentes contextos.

Una manera más sólida que comparar referencias directamente para la igualdad numérica sería usar la función refaddr proporcionada por Scalar::Util, después de asegurarse de que ambos lados en realidad son referencias.

+1

Si está utilizando una clase cuyos objetos tienen una sobremultificación nummification ('0 +'), o una sobrecarga '==' (tal vez a través de '<=>'), entonces es posible que realmente * quiera * es interceptada, personalizada sentido de igualdad Hacer una declaración general sin mencionar esas consideraciones parece demasiado fácil. Dicho esto, no puedo pensar en muchos escenarios en los que la ruta del código adoptada por la función del módulo sea una ruta crítica en la que intentas extraer hasta el último detalle del rendimiento que puedas. Pero si lo fuera, por supuesto querrías usar un '' '' 'normal. – tchrist

+0

De acuerdo. Es por eso que tu respuesta recibió un voto positivo de mi por mencionar eso. Hay muchos casos en los que uno podría querer comparar cosas para la igualdad, y el tipo de igualdad a usar debería ser considerado para cada caso individualmente. Sin embargo, la pregunta era bastante específica y, por lo tanto, obtuvo una respuesta específica. – rafl

+0

Merece una respuesta específica, también. Es por eso que obtuviste mi voto popular. ☺ – tchrist

15

La función que busca es RefAddr de Scalar::Util (después de asegurarse de que los valores que se comparan son en realidad referencias):

use Scalar::Util 'refaddr'; 

if ($obj1 and ref($obj1) and $obj2 and ref($obj2) and 
    refaddr($obj1) == refaddr($obj2)) 
{ 
    # objects are the same... 
} 
+2

Las extraordinarias medidas tomadas por la función refaddr() de cpan/List-Util/lib/Scalar/Util/PP.pm' para adivinar la dirección real del referente son excedidas solo por las medidas de la función blessed() para encontrar el Nombre del paquete. – tchrist

+4

Afortunadamente, como la distribución List-Util y el módulo Scalar :: Util que contiene, son módulos principales, y el núcleo está construido con un compilador C, prácticamente todo el mundo tiene el lujo de usar la versión C de Scalar :: Util :: refaddr, que es más o menos una verificación de bandera y una referencia. – rafl

+0

En realidad, hay una prueba en el código de mktables para ver si es un Scalar :: Util rápido o no. Debería haber recordado que solo podría ser una llamada C. – tchrist

7

Tengo que suponer que su #comment acerca de qué tan barata (= rápida) es la prueba de igualdad estaba allí por una razón. Dado eso, probablemente deberías seguir usando la prueba de igualdad económica. Es muy rápido, mucho más rápido que eq, y mucho menos que cualquier tipo de comparación profunda.

Es posible que un objeto con un operador == directa o indirectamente sobrecargado pueda usurpar la prueba para sus propios fines. Pero si es haciendo eso, incluso podría preferir su respuesta mediada.

El enfoque que tome puede depender de lo que sepa sobre las clases del objeto. Los enfoques que se aplican a casos generales no siempre son óptimos para casos específicos. Cuanto más sepa sobre algo, más podrá optimizarlo, y al revés también.

Si sabe sabe que no está utilizando una clase con sobrecarga aplicable, no hay razón para ir arrastrando una función de biblioteca no incorporada, y justa razón para no hacerlo. Si no sabe sobrecarga, o si lo sabe y no quiere que se aplique, entonces tal vez tome el enfoque lento.

Siempre y cuando entienda las preocupaciones de sobrecarga, es un error considerar que un enfoque es correcto y otro es incorrecto. Cada uno tiene su propósito. Si siempre estuvo mal hacer lo que está haciendo, entonces esa operación estaría prohibida o al menos advertida.

Notará que es no así marcado.

+1

Uno pensaría que todos los votantes bajos tendrían la valentía de deletrear qué es lo que creen que he dicho que está mal. Pero ellos no. Por lo tanto, aparentemente prefieren los disparos ocultos anónimos al discurso razonado. Si no puede justificar su voto, quizás no deba hacerlo. – tchrist

+1

No tengo ningún problema con lo que publicaste (y no votó negativamente) pero creo que es interesante que muchos carteles exijan explicaciones para los votos a favor, pero no para los votos a favor. No gasto tiempo justificando los 20 votos extras que doy todos los días. – friedo

+3

@friedo: Si crees que tengo razón, es suficiente saber que piensas que estoy en lo correcto. (Aun así, si hay un punto en particular que vale la pena enfatizar, los comentarios "+1 para ..." son razonablemente comunes.) Si crees que estoy equivocado, quiero saber * por qué * crees que estoy equivocado para que yo puede aclarar mi afirmación, refutar sus objeciones, o quizás incluso (horror de los horrores) darse cuenta de que sus objeciones son precisas y aprender algo de ellas. Esta es la razón por la que, al menos, quiero comentarios sobre los votos a favor, pero no me importa la posibilidad de votos alternos. –

Cuestiones relacionadas