2011-02-11 11 views
6

He estado leyendo acerca de esto que el tamaño de un objeto debe ser de al menos 1 byte (C++: What is the size of an object of an empty class?) y ¿qué tiene de malo tener dos objetos vacíos en la misma dirección? Después de todo, podemos tener dos indicadores para el mismo objeto.¿Por qué las direcciones de dos objetos diferentes deberían ser diferentes?

Google me dice que hay algo acerca de la regla fundemantal de identidad de objeto, pero no puedo encontrar información más detallada sobre eso.

Así que ... $ SUBJ.

+3

Cada vez que veo preguntas como esta creo que el mundo se ha mejorado, se creó StackOverflow. – sharptooth

Respuesta

5

Tener dos objetos en la misma dirección significaría que no habría forma de distinguir entre estos dos objetos al hacer referencia a ellos con los punteros. Por ejemplo, en el siguiente código:

EmptyClass o1; 
EmptyClass o2; 

EmptyClass * po = &o; 
po->foo(); 

se debe llamar al método foo en o1 o o2?

Podría argumentarse que como estos objetos no tienen datos ni métodos virtuales (de lo contrario, tendrían un tamaño distinto de cero), no importa en qué instancia se invoca el método. Sin embargo, esto se hace más importante cuando queremos probar si dos objetos son iguales (es decir, si son lo mismo):

template < typename T > 
bool isSame(T const & t1, T const & t2) 
{ 
    return &t1 == &t2; 
} 

EmptyClass o1; // one object and... 
EmptyClass o2; // ...a distinct object... 

assert(! isSame(o1, o2)); // ...should not be one and same object! 

Para un ejemplo más concreto, vamos a suponer que yo quiero asociar algunos objetos (que se podía decir entidades) con algunos valores, digamos en un recipiente asociativa:

Person you; 
Person me; 

// You and I are two different persons 
// (unless I have some dissociative identity disorder!) 
// Person is a class with entity semantics (there is only one 'me', I can't make 
// a copy of myself like I would do with integers or strings) 

std::map< Person *, std::string > personToName; 

personToName[&you] = "Andrew_Lvov"; 
personToName[&me] = "Luc Touraille"; 
// Oh, bother! The program confused us to be the same person, so now you and I 
// have the same name! 

Así que sí, todo se reduce a objeto de identidad: si los objetos se les permitió estar vacío, podrían ser privados de su identidad, que es simplemente no permitido por el idioma (afortunadamente).

+1

Sí, esa es una gran explicación, gracias. Un problema adicional que en realidad surge: ¿y si tienes una matriz de objetos vacíos? No puede seleccionar el miembro de la matriz, ya que el tamaño de la matriz es 0. –

+0

@Andrew_Lvov: Bueno, pensé en agregar esa observación, pero de hecho no estoy seguro de que esto sea un problema. De hecho, si tengo la matriz 'EmptyClass array [10]', el código 'array [3]' se traduce más o menos en '* (array + 3 * sizeof (EmptyClass))'; como 'sizeof (EmptyClass) == 0', terminamos accediendo al objeto en la dirección' array', que es de hecho el cuarto objeto de la matriz (así como también el primero, segundo, tercero, etc.). –

5

Cada objeto debe ocupar un espacio de almacenamiento distinto; de lo contrario, no puede desasignar un objeto sin desasignar otros que comparten almacenamiento con él.

Suponga que tiene dos objetos distintos en una única dirección:

Type* object1 = new Type(); //first object 
Type* object2 = new Type(); //second object 

y que se encuentren en la misma dirección, entonces

delete object1; 

lo que será delete d si ambos tienen la misma ¿dirección?

+3

Esta lógica no es realmente sólida. Si tuviéramos que permitir objetos de tamaño cero en la misma dirección, sería lógico declarar tanto 'new' como' delete' para dichos objetos como no-ops, es decir, 'new' devolvería una dirección arbitraria (está bien, ya que de todos modos, no es desreferenciable) y 'borrar 'simplemente no haría nada. – AnT

+0

@AndreyT - ¿Qué pasa con las cosas que heredan de los artículos vacíos – Flexo

+0

Creo que no es el punto. El operador nuevo podría devolver 0x1 predefinido para cada objeto vacío asignado y eliminar no podría hacer nada para esa dirección (sin datos, nada que asignar, nada que liberar). –

1

Cuando tiene dos punteros al mismo objeto, puede usarlos para manipular el objeto. Resultado = puede acceder al objeto.

Sin embargo, si tiene dos objetos en la misma dirección, ¿cómo los diferenciaría en la memoria? Si tuviera un puntero a esa dirección, ¿cómo sabría a qué objeto apuntaba su puntero?

De ahí la necesidad de diferentes direcciones para cada objeto, incluso si están vacías.

3

C++ tiene (entre otras cosas) una regla que dice que los punteros a objetos se comparan igual si y solo si los punteros se refieren al mismo objeto. Bajo el escenario que propone, esto ya no sería cierto.

También hay un poco de código que simplemente supone que sizeof también producirá un resultado estrictamente positivo. Sobresalen por ejemplo, un poco de código utiliza cosas como:

#define elements(array) ((sizeof(array)/sizeof(array[0])) 

con objetos con un tamaño de cero, esto se traduciría en 0/0, que es matemáticamente definido.

En lugar de hacer cambios en cualquier otro lugar para admitir un caso de esquina, era mucho más simple simplemente eliminar el caso de esquina para que se ajuste a las reglas existentes.

+0

El ejemplo con sizeof es en realidad un problema de implementación de lenguaje C++, no es un problema fundamental. –

+0

>> C++ tiene (entre otras cosas) una regla que dice que los punteros a los objetos se comparan igual si y solo si los punteros se refieren al mismo objeto. ¿Cuál debería ser esta regla cumplida? Por cierto, ¿dónde se describe esta regla? –

+0

@Andrew_Lvov: se describe en la norma §5.10.1: 'Dos punteros del mismo tipo se comparan igual si y solo si son ambos nulos, ambos apuntan al mismo objeto o función, o ambos señalan uno pasado el final de la misma matriz. –

0

Intente una analogía.

Si tiene dos automóviles y trata de que ocupen el mismo espacio físico, tendrá un accidente.

Si tiene dos objetos e intenta que ocupen el mismo espacio de memoria, también tendrá un bloqueo.

+0

Supongo que el automóvil debe ocupar espacio. ¿Qué pasa con un objeto que no tiene por qué? –

Cuestiones relacionadas