我試圖瞭解什麼似乎是一個怪異的行爲時分配一個新的值分配到堆棧上的對象(析構函數被調用兩次相同的數據集)。我就開始與代碼片段,其輸出:C++堆棧分配的對象分配和析構函數調用
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;
}
輸出:
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
我希望發生:
- 0X ...... 58被創建/初始化在堆棧上
- 0x ... 18在堆棧上創建/初始化
- Foo析構函數在0x ... 58上調用F1數據)
- 富析構函數被調用於0X ... 18(具有f數據)
居然會發生什麼:
- 0X ...... 58時生成/初始化堆棧
- 0X ... 18獲取創建/初始化堆棧上從0X ... 18(F2)
- 數據被複制到0X ... 58
- 富析構函數被調用於0X ... 18(具有f數據)
- 富析構函數被調用的0X ... 58(也具有f數據)
所以在最後,Foo析構函數被兩次調用相同的數據(f2)。很明顯,我錯過了一些關於內部工作原理的東西,所以有人可以請我指出正確的方向嗎?
因爲您已經複製了一個臨時對象,它將'f'所保持的名稱從''f1''更改爲''f2''',所以不會看到「f1」'析構函數的消息。因此,你首先會看到臨時的「f2」破壞,然後原始實例(現在稱爲「f2」)被破壞。請注意,數據不一樣;它是具有相同值的副本。 –
如果你的類有一個析構函數,它應該幾乎肯定也有一個拷貝構造函數和賦值運算符。 –
並且(可能)移動構造函數和移動賦值操作符(「五個規則」)。 –