Reputation: 2489
I have this following code which i can not understand:
#include <cstdio>
#include <iostream>
using namespace std;
class A
{
public:
int t = 0;
A(){
cout << "constructed" << t<< endl;
}
A (A&& a) {
cout << "in move ctor, moving"<< a.t << endl;
}
~A() {
cout << "deleting"<< t << endl;
}
};
A f1 (A a)
{
a.t = 1;
std::cout << "f1: " << endl;
return a;
}
int main() {
A a = f1(A()) ;
printf("what is happening\n");
}
and the output is
constructed0
in move ctor, moving0
f1:
in move ctor, moving1
in move ctor, moving0
deleting0
deleting1
deleting0
what is happening
deleting0
The thing that I can not understand is the phase where the temporary object created for f1 (the one with a.t=1) is being destroyed.
From the output I assume it is being destroyed at the and of the line A a = f1(A()) ;
While I thought it was created inside f1 and for f1, and therefore will be destroyed when exiting the function, before deleting0 is being called.
What am I missing?
Upvotes: 0
Views: 84
Reputation: 2489
So after a bit research I have the Answer.
Here is the disassembly of the code (changed the move constructor to a copy constructor for readability):
int A::counter = 0;
A f1 (A a)
{
400a18: 55 push %rbp
400a19: 48 89 e5 mov %rsp,%rbp
400a1c: 48 83 ec 10 sub $0x10,%rsp
400a20: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400a24: 48 89 75 f0 mov %rsi,-0x10(%rbp)
cout << __LINE__ << endl;
400a28: be 1d 00 00 00 mov $0x1d,%esi
400a2d: bf 80 13 60 00 mov $0x601380,%edi
400a32: e8 c1 fd ff ff callq 4007f8 <_ZNSolsEi@plt>
400a37: be 78 08 40 00 mov $0x400878,%esi
400a3c: 48 89 c7 mov %rax,%rdi
400a3f: e8 24 fe ff ff callq 400868 <_ZNSolsEPFRSoS_E@plt>
a.t = 1;
400a44: 48 8b 45 f0 mov -0x10(%rbp),%rax
400a48: c7 00 01 00 00 00 movl $0x1,(%rax)
std::cout << "f1: " << endl;
400a4e: be ce 0e 40 00 mov $0x400ece,%esi
400a53: bf 80 13 60 00 mov $0x601380,%edi
400a58: e8 fb fd ff ff callq 400858 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
400a5d: be 78 08 40 00 mov $0x400878,%esi
400a62: 48 89 c7 mov %rax,%rdi
400a65: e8 fe fd ff ff callq 400868 <_ZNSolsEPFRSoS_E@plt>
cout << __LINE__ << endl;
400a6a: be 20 00 00 00 mov $0x20,%esi
400a6f: bf 80 13 60 00 mov $0x601380,%edi
400a74: e8 7f fd ff ff callq 4007f8 <_ZNSolsEi@plt>
400a79: be 78 08 40 00 mov $0x400878,%esi
400a7e: 48 89 c7 mov %rax,%rdi
400a81: e8 e2 fd ff ff callq 400868 <_ZNSolsEPFRSoS_E@plt>
return a;
400a86: 48 8b 55 f0 mov -0x10(%rbp),%rdx
400a8a: 48 8b 45 f8 mov -0x8(%rbp),%rax
400a8e: 48 89 d6 mov %rdx,%rsi
400a91: 48 89 c7 mov %rax,%rdi
400a94: e8 dd 01 00 00 callq 400c76 <_ZN1AC1ERKS_>
}
400a99: 48 8b 45 f8 mov -0x8(%rbp),%rax
400a9d: c9 leaveq
400a9e: c3 retq
0000000000400a9f <main>:
int main() {
400a9f: 55 push %rbp
400aa0: 48 89 e5 mov %rsp,%rbp
400aa3: 53 push %rbx
400aa4: 48 83 ec 48 sub $0x48,%rsp
A a = f1(A()) ;
400aa8: 48 8d 45 e0 lea -0x20(%rbp),%rax
400aac: 48 89 c7 mov %rax,%rdi
400aaf: e8 2a 01 00 00 callq 400bde <_ZN1AC1Ev>
400ab4: 48 8d 55 e0 lea -0x20(%rbp),%rdx
400ab8: 48 8d 45 d0 lea -0x30(%rbp),%rax
400abc: 48 89 d6 mov %rdx,%rsi
400abf: 48 89 c7 mov %rax,%rdi
400ac2: e8 af 01 00 00 callq 400c76 <_ZN1AC1ERKS_>
400ac7: 48 8d 45 c0 lea -0x40(%rbp),%rax
400acb: 48 8d 55 d0 lea -0x30(%rbp),%rdx
400acf: 48 89 d6 mov %rdx,%rsi
400ad2: 48 89 c7 mov %rax,%rdi
400ad5: e8 3e ff ff ff callq 400a18 <_Z2f11A>
400ada: 48 8d 55 c0 lea -0x40(%rbp),%rdx
400ade: 48 8d 45 b0 lea -0x50(%rbp),%rax
400ae2: 48 89 d6 mov %rdx,%rsi
400ae5: 48 89 c7 mov %rax,%rdi
400ae8: e8 89 01 00 00 callq 400c76 <_ZN1AC1ERKS_>
400aed: 48 8d 45 c0 lea -0x40(%rbp),%rax
400af1: 48 89 c7 mov %rax,%rdi
400af4: e8 31 02 00 00 callq 400d2a <_ZN1AD1Ev>
400af9: 48 8d 45 d0 lea -0x30(%rbp),%rax
400afd: 48 89 c7 mov %rax,%rdi
400b00: e8 25 02 00 00 callq 400d2a <_ZN1AD1Ev>
400b05: 48 8d 45 e0 lea -0x20(%rbp),%rax
400b09: 48 89 c7 mov %rax,%rdi
400b0c: e8 19 02 00 00 callq 400d2a <_ZN1AD1Ev>
printf("what is happening\n");
400b11: bf d3 0e 40 00 mov $0x400ed3,%edi
400b16: e8 ed fc ff ff callq 400808 <puts@plt>
cout << __LINE__ << endl;
return a;
}
The Copy constructor is called "ZN1AC1ERKS" after mangling process.
As we can see, the temporary object that is being created for f1, is being created before the function call, in main, and not as i expected, in f1's scope.
The meaning is as follows:
Temporary objects being created for functions that are called by value are not created in the functions scope, but rather on the line called the function, thus they will be destroyed before the next line execution, in the ordinary first created last destroyed way.
Upvotes: 1