zoukankan      html  css  js  c++  java
  • 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
    <<<<<<<<<<<<<<<<<<<<<<<<<

    运行结果:

  • 相关阅读:
    Nginx编译参数详细注释(解释)(转载)
    linux 下开机同步时间
    115转存代码
    清除linux下history命令
    【python学习1】编写猜数字的小游戏
    对深层嵌套的代码进行重构
    JS对JSON的操作总结
    调程序的小女孩(感谢安徒生)(转)
    区块链资料
    aws创建实例 通过密钥登录后 更改root账号密码 创建普通账户 开放ssh密码登录 关闭root账号登录
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7668200.html
Copyright © 2011-2022 走看看