c++ 類的默認八種函數
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <string> class MyClass { public: MyClass(const char * str = nullptr); // 默認帶參構造函數 // 默認構造函數指不帶參數或者所有參數都有缺省值的構造函數 ~MyClass(void); // 默認析構函數 MyClass(const MyClass &); // 默認拷貝構造函數 MyClass & operator =(const MyClass &); // 默認重載賦值運算符函數 MyClass * operator &(); // 默認重載取址運算符函數 MyClass const * operator &() const; // 默認重載取址運算符const函數 MyClass(MyClass &&); // 默認移動構造函數 MyClass & operator =(MyClass &&); // 默認重載移動賦值操作符函數 private: char *m_pData; }; // 默認帶參構造函數 MyClass::MyClass(const char * str) { if (!str) { m_pData = nullptr; } else { this->m_pData = new char[strlen(str) + 1]; strcpy(this->m_pData, str); } std::cout << "默認帶參構造函數" << " this addr: " << this << std::endl; } // 默認析構函數 MyClass::~MyClass(void) { if (this->m_pData) { delete[] this->m_pData; this->m_pData = nullptr; } std::cout << "默認析構函數" << " this addr: " << this << std::endl; } // 默認拷貝構造函數 MyClass::MyClass(const MyClass &m) { if (!m.m_pData) { this->m_pData = nullptr; } else { this->m_pData = new char[strlen(m.m_pData) + 1]; strcpy(this->m_pData, m.m_pData); } std::cout << "默認拷貝構造函數" << " this addr: " << this << std::endl; } // 默認重載賦值運算符函數 MyClass & MyClass::operator =(const MyClass &m) { if ( this == &m ) { return *this; } delete[] this->m_pData; if (!m.m_pData) { this->m_pData = nullptr; } else { this->m_pData = new char[strlen(m.m_pData) + 1]; strcpy(this->m_pData, m.m_pData); } std::cout << "默認重載賦值運算符函數" << " this addr: " << this << std::endl; return *this; } // 默認重載取址運算符函數 MyClass * MyClass::operator &() { std::cout << "默認重載取址運算符函數" << " this addr: " << this << std::endl; return this; } // 默認重載取址運算符const函數 MyClass const * MyClass::operator &() const { std::cout << "默認重載取址運算符const函數" << " this addr: " << this << std::endl; return this; } // 默認移動構造函數 MyClass::MyClass(MyClass && m): m_pData(std::move(m.m_pData)) { std::cout << "默認移動構造函數" << std::endl; m.m_pData = nullptr; } // 默認重載移動賦值操作符函數 MyClass & MyClass::operator =(MyClass && m) { if ( this == &m ) { return *this; } this->m_pData = nullptr; this->m_pData = std::move(m.m_pData); m.m_pData = nullptr; std::cout << "默認重載移動賦值操作符函數" << " this addr: " << this << std::endl; return *this; } void funA(MyClass a) { std::cout << "調用funA函數" << " param addr: " << &a << std::endl; } void mytest1(void) { std::cout << "mytest1 >>>>" << std::endl; MyClass myclass1; // 等價於 MyClass myclass1 = MyClass(); // 調用默認帶參構造函數 myclass1 = MyClass(); // MyClass()為右值,需要右值引用 // 先調用默認帶參構造函數,然后調用默認重載取址運算符函數,最后調用默認重載移動賦值操作符函數 std::cout << "<<<<< mytest1" << std::endl; // 析構兩次 1: myclass1 = MyClass()中的MyClass() 2: MyClass myclass1 } void mytest2(void) { std::cout << "mytest2 >>>>" << std::endl; MyClass myclass1; // 等價於 MyClass myclass1 = MyClass(); // 調用默認帶參構造函數 MyClass myclass2(myclass1); // 調用默認拷貝構造函數 myclass2 = myclass1; // myclass2為左值,所以此操作為賦值操作,會調用默認重載取址運算符const函數,然后調用默認重載賦值運算符函數 funA(myclass1); // 參數傳值會導致賦值操作,會調用默認拷貝構造函數,然后funA函數調用默認重載取址運算符函數取得參數 funA(std::move(myclass1)); // funA函數的參數現為右值,會調用默認移動構造函數,然后funA函數調用默認重載取址運算符函數取得參數 // 在移動構造函數中對於基本類型所謂移動只是把其值拷貝,對於如string這類類成員來說才會真正的所謂資源移動 std::cout << "<<<<< mytest2" << std::endl; } void mytest3(void) { std::cout << "mytest3 >>>>" << std::endl; funA(MyClass()); // 會調用默認帶參構造函數,生成該類的對象,然后funA函數調用默認重載取址運算符函數取得參數 std::cout << "<<<<< mytest3" << std::endl; // 析構一次 1: funA(MyClass())中的MyClass()形成的對象,是在funA函數結束調用的時候,調用默認析構函數 } void mytest(void) { std::cout << "<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl; mytest1(); mytest2(); mytest3(); std::cout << "<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl; } int main(int argc, char * argv[], char * envp[]) { mytest(); system("pause"); return 0; }
<<<<<<<<<<<<<<<<<<<<<<<<< mytest1 >>>> 默認帶參構造函數 this addr: 0x7ffca6b2eed8 默認帶參構造函數 this addr: 0x7ffca6b2eed0 默認重載取址運算符函數 this addr: 0x7ffca6b2eed0 默認重載移動賦值操作符函數 this addr: 0x7ffca6b2eed8 默認析構函數 this addr: 0x7ffca6b2eed0 <<<<< mytest1 默認析構函數 this addr: 0x7ffca6b2eed8 mytest2 >>>> 默認帶參構造函數 this addr: 0x7ffca6b2eed8 默認拷貝構造函數 this addr: 0x7ffca6b2eed0 默認重載取址運算符const函數 this addr: 0x7ffca6b2eed8 默認重載賦值運算符函數 this addr: 0x7ffca6b2eed0 默認拷貝構造函數 this addr: 0x7ffca6b2eeb8 調用funA函數 param addr: 默認重載取址運算符函數 this addr: 0x7ffca6b2eeb8 0x7ffca6b2eeb8 默認析構函數 this addr: 0x7ffca6b2eeb8 默認移動構造函數 調用funA函數 param addr: 默認重載取址運算符函數 this addr: 0x7ffca6b2eeb0 0x7ffca6b2eeb0 默認析構函數 this addr: 0x7ffca6b2eeb0 <<<<< mytest2 默認析構函數 this addr: 0x7ffca6b2eed0 默認析構函數 this addr: 0x7ffca6b2eed8 mytest3 >>>> 默認帶參構造函數 this addr: 0x7ffca6b2eed8 調用funA函數 param addr: 默認重載取址運算符函數 this addr: 0x7ffca6b2eed8 0x7ffca6b2eed8 默認析構函數 this addr: 0x7ffca6b2eed8 <<<<< mytest3 <<<<<<<<<<<<<<<<<<<<<<<<<
運行結果: