一、拷貝函數概述
拷貝函數是C++中的類成員函數之一,用於在對象創建時或對象作為函數參數傳遞時,將一個對象的值複製給另一個對象。當沒有定義拷貝函數時,C++編譯器將自動生成一個淺複製的默認拷貝函數。默認拷貝函數的作用是將一個對象的成員變量值複製給另一個對象,但對於指針類型等複雜類型,這種複製方式顯然是不合適的。
二、淺拷貝和深拷貝的區別
淺拷貝是指在執行拷貝過程時,只是將內存中的數據進行簡單的複製,這樣將得到兩個指針指向同一塊內存地址。
深拷貝是指在執行拷貝過程時,將自定義類型的內存塊複製到新的內存塊中,從而這兩個對象互不干擾。
//示例代碼 #include #include using namespace std; class String { public: String(const char* str = NULL);//普通構造函數 String(const String &other);//拷貝構造函數 ~String();//析構函數 String& operator =(const String& other);//賦值函數 private: char *m_data;//用於保存字符串 int m_len;//用於保存字符串長度 }; String::String(const char* str) { if (str == NULL) { m_data = new char[1]; *m_data = '\0'; m_len = 0; } else { m_len = strlen(str); m_data = new char[m_len + 1]; strcpy(m_data, str); } } String::String(const String &other) { m_len = other.m_len; m_data = new char[m_len + 1]; strcpy(m_data, other.m_data); } String::~String() { delete[] m_data; } String& String::operator =(const String& other) { if (this == &other)//檢查自賦值 return *this; delete[] m_data;//釋放舊空間 m_len = other.m_len; m_data = new char[m_len + 1]; strcpy(m_data, other.m_data); return *this; }
三、深拷貝的實現
為了實現深拷貝,我們需要自定義拷貝函數(拷貝構造函數、賦值函數),以避免默認拷貝函數的淺複製行為。拷貝構造函數用於在對象創建時複製一個現有對象,賦值函數則用於在對象已經存在時將一個現有對象的值複製給另一個對象。下面的代碼就是一個使用深拷貝的例子。
//示例代碼 #include #include using namespace std; class Student { public: Student(); Student(const char *name, int age, const char *gender); Student(const Student &stu); ~Student(); const char* getName() const; int getAge() const; const char* getGender() const; void setName(const char *name); void setAge(int age); void setGender(const char *gender); Student& operator=(const Student &stu); private: char *m_name; int m_age; char *m_gender; }; Student::Student(): m_name(NULL), m_age(0), m_gender(NULL) {} Student::Student(const char *name, int age, const char *gender) { if(name) { m_name = new char[strlen(name) + 1]; strcpy(m_name, name); } else { m_name = new char[1]; *m_name = '\0'; } m_age = age; if(gender) { m_gender = new char[strlen(gender) + 1]; strcpy(m_gender, gender); } else { m_gender = new char[1]; *m_gender = '\0'; } } Student::Student(const Student &stu) { if(stu.m_name) { m_name = new char[strlen(stu.m_name) + 1]; strcpy(m_name, stu.m_name); } else { m_name = new char[1]; *m_name = '\0'; } m_age = stu.m_age; if(stu.m_gender) { m_gender = new char[strlen(stu.m_gender) + 1]; strcpy(m_gender, stu.m_gender); } else { m_gender = new char[1]; *m_gender = '\0'; } } Student::~Student() { if(m_name) { delete[] m_name; } if(m_gender) { delete[] m_gender; } } const char* Student::getName() const { return m_name; } int Student::getAge() const { return m_age; } const char* Student::getGender() const { return m_gender; } void Student::setName(const char *name) { if(name) { m_name = new char[strlen(name) + 1]; strcpy(m_name, name); } else { m_name = new char[1]; *m_name = '\0'; } } void Student::setAge(int age) { m_age = age; } void Student::setGender(const char *gender) { if(gender) { m_gender = new char[strlen(gender) + 1]; strcpy(m_gender, gender); } else { m_gender = new char[1]; *m_gender = '\0'; } } Student& Student::operator=(const Student &stu) { if(this == &stu) {// 檢查自賦值 return *this; } if(m_name) { delete[] m_name; } if(stu.m_name) { m_name = new char[strlen(stu.m_name) + 1]; strcpy(m_name, stu.m_name); } else { m_name = new char[1]; *m_name = '\0'; } m_age = stu.m_age; if(m_gender) { delete[] m_gender; } if(stu.m_gender) { m_gender = new char[strlen(stu.m_gender) + 1]; strcpy(m_gender, stu.m_gender); } else { m_gender = new char[1]; *m_gender = '\0'; } return *this; }
四、拷貝函數的使用場景
在以下場景中,拷貝函數尤為重要:
1、當類具有指針成員時,必須使用深拷貝,以避免淺複製時指針成員指向同一個地址。
2、當類中的成員總量較大時,賦值操作會佔據很多時間,因此深拷貝函數可以顯著提高代碼的執行效率。
3、當類中包含了單例模式時,拷貝構造函數和賦值構造函數就有着更為重要的意義。
五、總結
在C++編程中,拷貝函數是相當重要的一個內容。在類的實例化以及類實例的拷貝過程中,深拷貝有時還需要重寫拷貝函數來保證正確性。因此,C++工程師必須充分理解拷貝函數的內涵,能夠正確地實現它,以避免因深複製的不當實現而導致程序的不穩定。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/304552.html