Cierto lo que has dicho, pero me gustaría re-puntualizar una cosa. Si bien es cierto que los valores de los punteros serán independientes después de la copia, como normalmente lo que hacemos con los punteros miembro (que normalmente van a apuntar a otros objetos construidos en la pila) va a ser acceder a sus miembros con puntero->miembro en lugar de cambiar directamente su valor, y como muchas veces esos objetos a los que apunta el puntero se construyen dentro de la propia clase (es decir, son objetos miembro construidos con memoria dinámica), es muy común el error de suponer que al copiar las dos instancias van a contener punteros a dos objetos de la pila distintos (= a dos objetos miembro distintos) cuando no es así. Me imagino que eso tu ya lo sabes pero es algo que no siempre es obvio en C++ y lo explico en pro del barrapuntero C++ero novato. Por supuesto el problema es recursivo y si tenemos miembros que son instancias (no punteros) pero a su vez contienen punteros a objetos tenemos el mismo problema (pero más dificil de encontrar, si cabe.)
Esto es así porque si hacemos la asignación de dos instancias de una clase en la que no se ha escrito un constructor de asignación por defecto se llama al constructor de copia. Si este tampoco lo hemos definido se toma el constructor de copia por defecto que hace una copia bit a bit de la memoria. Por lo tanto si el objeto tiene punteros como la memoria se ha copiado bit a bit tendremos dos instancias cuyos miembros puntero son variables independientes pero cuyos valores son iguales, y como los valores de un puntero son posiciones de memoria, apuntan a las mismas posiciones (= al mismo objeto.) Cualquier cambio en el puntero miembro de uno afecta al otro. Esto normalmente se traduce en un ¡ouch! muy grande cuando lo descubrimos (y en una fuga de memoria muy típica.)
Es fácil hacer la prueba (aviso: código muy warro):
#include
class Int
{
public:
int valor;
Int(int nuevoValor = 0) { valor = nuevoValor;}
};
class Prueba
{
public:
int nopuntero;
Int *puntero;
Prueba(int valornopuntero) {
nopuntero = valornopuntero;
puntero = new Int(3);
}
void imprimeValores() {
printf("No-Puntero: %d ", nopuntero);
printf("Puntero: %d\n", puntero->valor);
}
void cambiaPuntero(int nuevoValor) {
puntero->valor = nuevoValor;
}
};
int main() {
Prueba p(10);
p.imprimeValores();// 10, 1
Prueba p2(20);
p2.imprimeValores();// 20, 2
// Cambiamos los dos punteros para comprobar que efectivamente tienen valores distintos
p.cambiaPuntero(3);
p2.cambiaPuntero(4);
p.imprimeValores();// 10, 3
p2.imprimeValores();// 20, 4
// Ahora copiamos a capón p en p2:
Re-Puntualicemos :-)
(Puntos:3, Informativo)( http://barrapunto.com/ )
Esto es así porque si hacemos la asignación de dos instancias de una clase en la que no se ha escrito un constructor de asignación por defecto se llama al constructor de copia. Si este tampoco lo hemos definido se toma el constructor de copia por defecto que hace una copia bit a bit de la memoria. Por lo tanto si el objeto tiene punteros como la memoria se ha copiado bit a bit tendremos dos instancias cuyos miembros puntero son variables independientes pero cuyos valores son iguales, y como los valores de un puntero son posiciones de memoria, apuntan a las mismas posiciones (= al mismo objeto.) Cualquier cambio en el puntero miembro de uno afecta al otro. Esto normalmente se traduce en un ¡ouch! muy grande cuando lo descubrimos (y en una fuga de memoria muy típica.)
Es fácil hacer la prueba (aviso: código muy warro):
#include
class Int
{
public:
int valor;
Int(int nuevoValor = 0) { valor = nuevoValor;}
};
class Prueba
{
public:
int nopuntero;
Int *puntero;
Prueba(int valornopuntero) {
nopuntero = valornopuntero;
puntero = new Int(3);
}
void imprimeValores() {
printf("No-Puntero: %d ", nopuntero);
printf("Puntero: %d\n", puntero->valor);
}
void cambiaPuntero(int nuevoValor) {
puntero->valor = nuevoValor;
}
};
int main() {
Prueba p(10);
p.imprimeValores();
Prueba p2(20);
p2.imprimeValores();
p.cambiaPuntero(3);
p2.cambiaPuntero(4);
p.imprimeValores();
p2.imprimeValores();