A.connected_to[0] = &B;
sirve Copiar algo: el valor del puntero temporal de la expresión &B
.
La clase de plantilla vectorial siempre realizará la construcción y destrucción automática de copias, pero la construcción de copia de un tipo primitivo equivale a la asignación y destrucción de un tipo primitivo, incluidos los punteros, es una operación no operativa.
Un puntero es un tipo muy básico: casi nada se hace automáticamente cuando se utilizan punteros. Debajo del capó es solo un valor integral correspondiente a una dirección en la memoria. Cuando desreferencia un puntero, el compilador simplemente confía en que el puntero mantenga la dirección de (o "apunte a") un objeto del tipo correcto.
Por ejemplo, las clases dadas Foo y Bar que no están relacionados por herencia:
Foo *ptr1, *ptr2;
Bar *ptr3;
// All pointers are uninitialized.
// Dereferencing them is undefined behavior. Most likely a crash.
// The compiler will almost certainly issue a warning.
ptr1= new Foo(); // ptr1 now points to a valid Foo.
ptr2 = ptr1; // ptr2 points to the same Foo.
ptr3=(Bar*)ptr1; // This is an obvious programmer error which I am making here for demonstration.
// ptr3 points to the same block of memory as ptr1 & 2.
// Dereferencing it is likely to do strange things.
delete ptr1; // The compiler is allowed to set ptr1 to 0, but you can't rely on it.
// In either case dereferencing ptr1 is once again undefined behavior
// and the value of ptr2 is unchanged.
El compilador es mucho menos probable que emitir una advertencia si ve ptr1
sin referencia que después de la eliminación de antes de la inicialización. Prácticamente nunca emitirá una advertencia si desreferencia ptr2
después de eliminar el objeto a través de ptr1
. Si no tiene cuidado como otros lo han advertido, su vector de punteros puede llevarlo a inadvertidamente invocar un comportamiento indefinido de esta manera.
que presentó el muy mal molde de un Foo*
a un Bar*
para ilustrar la confianza absoluta del compilador en ti. El compilador le permite hacerlo y gustosamente tratará los bits como si fueran una barra cuando desreferencia ptr3
.
La biblioteca estándar de C++ ofrece pocas clases de plantillas que ofrecen un comportamiento tipo puntero con mucha más seguridad automática. Por ejemplo, el std::shared_pointer
:
std::shared_ptr
es un puntero inteligente que gestiona la vida de un objeto, normalmente asignados con new
. Varios objetos shared_ptr
pueden administrar el mismo objeto; el objeto se destruye cuando se destruye o restablece el último shared_ptr
apuntando a él. El objeto es destruido mediante delete-expression o un eliminador personalizado que se suministra a shared_ptr
durante la construcción.
Si su entorno aún no proporciona la biblioteca estándar de C++ 11, podría proporcionar la biblioteca de impulso o el espacio de nombres std::tr1::
. Ambos proporcionan un shared_ptr
muy similar. std::auto_ptr
, que está seguro de tener, es similar pero permite que solo un auto_ptr
haga referencia a un objeto en un momento determinado. (C++ 11 introduce std::unique_ptr
como un reemplazo previsto para auto_ptr
. El auto_ptr
es incompatible con la mayoría de los contenedores de la plantilla std. unique_ptr
se pueden colocar en un contenedor de plantilla con std::move
.)
Es posible romper cualquiera de estos clases guardando u obteniendo el puntero y monkeying con ello, por ejemplo
Foo *basic_ptr=new Foo();
std::auto_ptr<Foo> fancy_ptr(basic_ptr);
delete basic_ptr; // Oops! This statement broke our auto_ptr.
También se romperá si se pasa en una dirección de una variable en el almacenamiento automático:
Foo aFoo;
std::auto_ptr<Foo> fancy_ptr(&aFoo); // automatic storage automatically breaks auto_ptr
Si usted acaba de hacer std::shared_ptr<sn> fresh_sn(new sn())
y luego usar un std::vector< std::shared_ptr<sn> >
se le multa.
Probar cosas suele ser una buena forma de aprender cómo funcionan realmente. Puedo manejar simples yy * con tipos primitivos, y pasarlos por referencia, etc. a funciones, pero lo anterior requiere comprender cómo struct y vector se implementan etc. hasta cierto punto =) – Deniz
Para aprender, sugiero que implemente casos mínimos de prueba de los diferentes enfoques que considera; use gdb u otro depurador para ejecutar estos ejemplos mínimos y observe cómo se comportan en detalle, de lo que puede tomar una decisión informada. –