Basicamente estas accediendo a memoria ya liberada.
https://en.cppreference.com/w/cpp/language/rule_of_threeSupongamos que:
vector::vector(int t):tamano(t) {
n = new int[tamano];
std::cout << "ctor n " << n << " object " << this << std::endl;
llenar();
}
vector::~vector() {
std::cout << "dtor n " << n << " object " << this << std::endl;
delete[] n;
}
int main() {
vector a, b;
a.visualizar();
b.visualizar();
vector z = a;
ctor n 0000020069C0A6E0 object 000000C9E96FF838 //constructor de a
ctor n 0000020069C0A720 object 000000C9E96FF848 //constructor de b
1 7 4 0 9
4 8 8 2 4
dtor n
0000020069C0A6E0 object
000000C9E96FF878 //destructor de z!
dtor n 0000020069C0A720 object 000000C9E96FF848 //destructor de b
dtor n
0000020069C0A6E0 object 000000C9E96FF838 //destructor de a
"Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special member functions will be called, if accessible, and if they are not user-defined, they are implicitly-defined by the compiler."
¿Que definio el compilador para el constructor de copia? Una copia byte por byte:
0003c 48 8d 44 24 68 lea rax, QWORD PTR z$[rsp]
00041 48 8d 4c 24 28 lea rcx, QWORD PTR a$[rsp]
00046 48 8b f8 mov rdi, rax
00049 48 8b f1 mov rsi, rcx
0004c b9 10 00 00 00 mov ecx, 16
00051 f3 a4 rep movsb
Por eso z.n es igual a a.n y eso no es bueno ya que se terminara liberando dos veces.
Si lo definimos nosotros:
vector(const vector &r) : vector(r.tamano)
{
memcpy(n
, r.
n, tamano
* sizeof(int)); }
ctor n 0000025A0CD6A820 object 000000935CFCFB88 //a
ctor n 0000025A0CD6A740 object 000000935CFCFB98 //b
1 7 4 0 9
4 8 8 2 4
ctor n 0000025A0CD6A760 object 000000935CFCFBC8 //z
dtor n 0000025A0CD6A760 object 000000935CFCFBC8 //~z
dtor n 0000025A0CD6A740 object 000000935CFCFB98 //~b
dtor n 0000025A0CD6A820 object 000000935CFCFB88 //~a
Ahora pasamos a probar:
vector c;
c = a + b;
c.visualizar();
Y comento el delete[] del destructor para que no explote el programa.
ctor n 0x8d13f0 object 0x79fdf0 //a
ctor n 0x8d1410 object 0x79fde0 //b
1 7 4 0 9
4 8 8 2 4
ctor n 0x8d1870 object 0x79fdd0 //c
ctor n
0x8d1890 object 0x79fe00 //resultado
dtor n
0x8d1890 object 0x79fe00 //~resultado
9263792 0 9240912 0 13
dtor n
0x8d1890 object 0x79fdd0 //~c
¿Cual es el problema? El operador de asignacion definido por el compilador hace que c.n sea igual a resultado.n (un n que inmediatamente es liberado al ejecutarse el destructor del objeto resultado).
Fijate si podes implementarlo siguiendo la logica demostrada en el enlace del principio de mi mensaje.
Tendrias que llegar a algo asi con el main original:
ctor n 0xae13f0 object 0x79fdf0 //a
ctor n 0xae1410 object 0x79fde0 //b
1 7 4 0 9
4 8 8 2 4
ctor n 0xae1870 object 0x79fdd0 //c
ctor n 0xae1890 object 0x79fe00 //resultado
ope= n 0xae1870 object 0x79fdd0 //c = resultado
dtor n 0xae1890 object 0x79fe00 //~resultado
5 15 12 2 13
ctor n 0xae1890 object 0x79fdc0 //d y resultado son lo mismo en este caso, esta optimizada la asignacion y por eso funciona
5 15 12 2 13
dtor n 0xae1890 object 0x79fdc0 ;~d
dtor n 0xae1870 object 0x79fdd0 ;~c
dtor n 0xae1410 object 0x79fde0 ;~b
dtor n 0xae13f0 object 0x79fdf0 ;~a