c++ 類的默認八種函數


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
<<<<<<<<<<<<<<<<<<<<<<<<<

 

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM