C ++ Assigning an object with a dedicated stack and calling the destructor
I am trying to figure out what seems to be some weird behavior when assigning a new value to an object allocated on the stack (the destructor is called twice for the same dataset). I'll just start with a piece of code and its output:
class Foo {
public:
Foo(const string& name) : m_name(name) {
log("constructor");
}
~Foo() {
log("destructor");
}
void hello() {
log("hello");
}
private:
string m_name;
void log(const string& msg) {
cout << "Foo." << this << " [" << m_name << "] " << msg << endl;
}
};
int main() {
{
Foo f {"f1"};
f.hello();
f = Foo {"f2"};
f.hello();
}
cout << "scope end" << endl;
}
Output:
Foo.0x7fff58c66a58 [f1] constructor
Foo.0x7fff58c66a58 [f1] hello
Foo.0x7fff58c66a18 [f2] constructor
Foo.0x7fff58c66a18 [f2] destructor
Foo.0x7fff58c66a58 [f2] hello
Foo.0x7fff58c66a58 [f2] destructor
scope end
What I expected to see:
- 0x ... 58 is created / initialized on the stack
- 0x ... 18 is created / initialized on the stack
- Foo destructor is called at 0x ... 58 (with data f1)
- Foo destructor is called on 0x ... 18 (with data f2)
What actually happens:
- 0x ... 58 is created / initialized on the stack
- 0x ... 18 is created / initialized on the stack
- data from 0x ... 18 (f2) is copied to 0x ... 58
- Foo destructor is called on 0x ... 18 (with data f2)
- Foo destructor is called on 0x ... 58 (also with data f2)
So in the end, Foo destructor is called twice for the same data (f2) . Clearly I missed something about how this works internally, so can someone point me in the right direction?
source to share
Before creating the second object Foo
, you only have one object at the address 0x..58
.
Address: 0x..58 Data: { m_name "f1" }
Address: 0x..18 Data: unknown
The line f = Foo {"f2"};
first creates a new Foo object whose value m_name
is "f2"
, and stores it at the address 0x..18
. Then it assigns that object to a variable f
.
This assignment does not destroy the preexisting object in f
, it only copies data items into it. Since Foo objects only have one data item m_name
, the assignment simply copies the second object m_name
into the first.
Address: 0x..58 Data: { m_name "f2" }
Address: 0x..18 Data: { m_name "f2" }
The destructors are then called for each of these objects. Inference does not mean that the same object is destroyed twice, it just means that both objects have the same m_name
.
source to share