class yitem {
public:
yitem(const char *s1): m_data(s1) { m_str = new string("abc"); }
~yitem() { delete m_str; }
string & get_data() { return m_data; }
private:
string m_data;
string *m_str = nullptr;
};
int main() {
vector<yitem> v1;
yitem a("A");
v1.push_back(a); // 這裡發生拷貝構造
return 0;
}
Valgrind 報告內存洩漏,原因在於 `yitem` 包含裸指針 `m_str`,但未定義拷貝構造函數與拷貝賦值運算符。
`vector::push_back` 會觸發元素的拷貝構造。編譯器自動生成的默認拷貝構造僅執行淺拷貝(逐位複製),導致新對象的 `m_str` 指向同一塊堆內存。當臨時對象 `a` 析構時 `delete m_str` 釋放內存,vector 內的對象持有野指針;程序結束 vector 析構再次 `delete` 同一地址 → 雙重釋放/內存洩漏/未定義行為。
class yitem {
public:
yitem(const char *s1): m_data(s1), m_str(new string("abc")) {}
// 拷貝構造
yitem(const yitem& other): m_data(other.m_data), m_str(new string(*other.m_str)) {}
// 拷貝賦值
yitem& operator=(const yitem& other) {
if (this != &other) {
m_data = other.m_data;
*m_str = *other.m_str;
}
return *this;
}
~yitem() { delete m_str; }
// ...
};
#include <memory>
class yitem {
string m_data;
unique_ptr<string> m_str; // 或 shared_ptr
public:
yitem(const char *s1): m_data(s1), m_str(make_unique<string>("abc")) {}
// 無需顯式聲明析構/拷貝/移動,unique_ptr 禁止拷貝,vector 需存放 unique_ptr 或用 shared_ptr
};
若 vector 必須存值類型,改用 `shared_ptr
掌握資源管理語義,才能寫出無洩漏、異常安全的 C++ 代碼。