當類對象以值傳遞方式作為函數參數時,函數結束後是否會調用該對象的析構函數?這涉及 C++ 對象生命周期管理的核心機制。
會調用析構函數。 但前提是:非引用傳遞(即值傳遞)的情況下。若使用引用傳遞(&)或指針傳遞,則不會在函數結束時調用析構函數。
若類內部管理動態資源(如裸指針 int* data),且未正確實現拷貝構造函數與拷貝賦值運算符(違反「三法則/五法則」),值傳遞會導致:
class MyClass {
int* data;
public:
MyClass(int size) : data(new int[size]) {}
// 缺少拷貝構造函數 → 淺拷貝 → 危險!
~MyClass() { delete[] data; }
};
void func(MyClass obj) { } // 值傳遞
int main() {
MyClass a(10);
func(a); // func 結束時析構副本,釋放 data
// a 後續析構再次 delete[] data → 錯誤!
}
void func(const MyClass& obj) { } // 無拷貝,無析構,高效且安全
避免拷貝開銷,且不觸發析構,是首選方式。
unique_ptr/shared_ptr)或標準容器(vector/string),編譯器自動生成正確的移動/拷貝語義(Rule of Zero)。若函數內部確需修改對象且不影響原對象,值傳遞語義正確,但務必確保類資源管理正確。
| 傳遞方式 | 是否拷貝 | 函數結束時調用析構 | 典型場景 |
|---|---|---|---|
值傳遞 T obj | 是(拷貝構造) | 是(銷毀副本) | 需修改副本、小型對象 |
引用傳遞 T& obj | 否 | 否 | 修改原對象、大型對象 |
常量引用 const T& obj | 否 | 否 | 只讀訪問、大型對象(推薦默認) |
右值引用 T&& obj | 否(移動語義) | 視情況 | 移動語義、完美轉發 |
理解參數傳遞的對象生命周期,是編寫健壯、高效 C++ 代碼的基石。現代 C++ 提倡「以值傳遞小對象,以 const 引用傳遞大對象,以右值引用實現移動」,並配合 RAII 與智能指針自動管理資源。