美文网首页
c++ 类的 8种默认函数

c++ 类的 8种默认函数

作者: simbanyan | 来源:发表于2020-09-06 18:43 被阅读0次
#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
<<<<<<<<<<<<<<<<<<<<<<<<<

相关文章

  • 面向对象

    面向对象技术的基本概念是:对象,类,继承。C++中的空类默认产生哪些类成员函数?默认产生构造函数,析构函数,拷贝构...

  • 类可以没有构造函数和析构函数吗

    C++提供的默认函数 首先说一下一个C++的空类,编译器会加入哪些默认的成员函数 默认构造函数和拷贝构造函数 析构...

  • C++:面向对象基础

    构造函数 C++中有三种构造函数:默认构造函数,有参构造函数,拷贝构造函数 类对象的初始化 括号法//默认构造函数...

  • [剑指offer]01-赋值运算符函数

    在面向对象C++语言中,用户定义一个类时,会默认生成四个成员函数:默认构造函数、默认析构函数、默认复制构造函数和默...

  • c++面向对象

    c++定义类 成员和成员函数 成员函数可以在内部定义,也可在内部声明,外部定义。 类的构造函数(有默认): 在类...

  • c++构造函数

    构造函数 引入 在c++的类中,构造函数是一种特殊的成员函数,在每次创建创建一个类的时候会默认调用构造函数进行初始...

  • C++对象模型3——默认构造/拷贝构造函数

    默认构造函数 在C++ Primer中有一句话:只有当类没有声明任何构造函数函数时,编译器才会自动地生成默认构造函...

  • 2018-9-5 鼎桥通信C++面经

    鼎桥通信C++面经 类与结构体的区别 默认的访问权限:(1)C++结构体内部成员变量及成员函数默认的访问级别是pu...

  • 2.4 析构函数和Halcon算子

    所有的HALCON/C++类都提供了默认的析构函数用来自动销毁对应的内存。对于某些类,析构函数基于适合的算子: W...

  • C++对象的初始化方式

    对象初始化可以分为默认初始化、直接初始化、拷贝初始化以及值初始化。C++的类默认提供了六种函数:构造函数、析构函数...

网友评论

      本文标题:c++ 类的 8种默认函数

      本文链接:https://www.haomeiwen.com/subject/xcocektx.html