c++ 类默认构造函数
在c++工程中,当用户新设计一个类的时候,编译器会给类生成默认的一些函数和运算操作符,以满足大部分使用过程中的操作,今天总结一下,以免忘记。
- 类的默认八个函数
1、默认构造函数;2、默认拷贝构造函数;3、默认析构函数;4、默认重载赋值运算符函数;5、默认重载取址运算符函数;6、默认重载取址运算符const函数;7、默认移动构造函数(C++11);8、默认重载移动赋值操作符函数(C++11) 下面用代码进行展示如果重写的格式
class A{
public://默认构造函数,什么都不做A();//A a;或者 A* a = new A;时被调用//默认拷贝构造函数A(const A&);//默认析构函数,什么都不做~A();//在调用delete a;时候被调用,或者在函数内局部变量生命周期结束后被调用//默认重载赋值运算符函数A& operator = (const A&);//在auto a2 = a;时候被调用//默认重载取址运算符函数A* operator &();//在调用 auto ptr = &a;时被调用(取地址时候)一版不用重载,智能指针会重载,默认结果为this//默认重载取址运算符const函数;const A* operator & () const;//如果a是一个const对象,此函数被调用;例如const A a;auto ptr = &a;//默认移动构造函数(C++11)A(A&&);//使用移动语意的时候被调用 例如:A a2 = std::move(a); 一般用于深拷贝,若不重写和赋值运算符函数一样//默认重载移动赋值操作符函数(C++11)A& operator = (const A&&);//当a为右值的时候,且用到=操作符的时候;比如a = A();
} 下面用测试用例来说明每个函数的被调用情况
#define _CRT_SECURE_NO_WARNINGS#include
#include
#include #include
#include 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
<<<<<<<<<<<<<<<<<<<<<<<<<
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
