#include<iostream>classStu{private:
std::string name ="无名氏";int age =18;public:Stu();Stu(std::string name,int age);Stu(const Stu &s);Stu(Stu &&s);
Stu &operator=(const Stu &s);
Stu &operator=(Stu &&s);~Stu();};
1.2 test/Student.cpp
#include"Student.h"Stu::Stu(){ std::cout <<"执行了无参构造函数!"<< std::endl;};Stu::Stu(std::string name,int age){ std::cout <<"执行了有参构造函数!"<< std::endl;};Stu::Stu(const Stu &s){ std::cout <<"执行了拷贝构造函数!"<< std::endl;};Stu::Stu(Stu &&s){ std::cout <<"执行了移动构造函数!"<< std::endl;};
Stu &Stu::operator=(const Stu &s){ std::cout <<"执行了拷贝赋值运算符函数!"<< std::endl;};
Stu &Stu::operator=(Stu &&s){ std::cout <<"执行了移动赋值运算符函数!"<< std::endl;};Stu::~Stu(){ std::cout <<"执行了析构函数!"<< std::endl;};
1.3 test/C++类的六个特殊成员函数.cpp
#include<iostream>#include"Student.h"// TODO 这个必须要加intmain(){// 类的六个特殊成员函数总结如下:// 普通构造函数(无参构造函数:Stu()、有参构造函数:Stu(std::string name, int age))// 拷贝构造函数:Stu(const Stu &s)// 移动构造函数:Stu(Stu &&s)// 拷贝赋值运算符函数:Stu &operator=(const Stu &s)// 移动赋值运算符函数:Stu &operator=(Stu &&s)// 析构函数:~Stu()
Stu s1;
Stu s2("张三",28);
Stu s3 = s2;
Stu s4 = std::move(s3);
Stu s5;
s5 = s4;
Stu s6;
s6 = std::move(s5);
std::cout << std::endl <<"执行了main函数"<< std::endl << std::endl;return0;}
#include<iostream>//--------------------------------------------------------------------------------classAA{private:
std::string name ="";int*AA_d =nullptr;public:explicitAA(std::string name){// 单一参数的构造函数最好加上explicit,避免隐式转换this->name = name;
AA_d =newint(666);// TODO 这里要给定指向,因为后面有*AA_d
std::cout <<this->name <<" "<<"执行了无参构造函数!"<< std::endl;
std::cout <<this->name <<" "<<"指针指向的地址:"<< AA_d << std::endl;
std::cout <<this->name <<" "<<"指针指向的地址的内容:"<<*AA_d << std::endl;
std::cout <<this->name <<" "<<"指针自身的地址:"<<&AA_d << std::endl;
std::cout <<"----------------------------------"<< std::endl;};~AA(){delete AA_d;
AA_d =nullptr;
std::cout << name <<" "<<"执行了析构函数!"<< std::endl;};};//--------------------------------------------------------------------------------classStu{public:
std::string name ="无名氏";int age =18;int*point =nullptr;
AA *p_internal =nullptr;// TODO 1.指向内部生成的内部对象,要在析构函数里面先释放后置空;
AA *p_external =nullptr;// TODO 2.指向外部传递的外部对象,不用在析构函数里面管理;public://==========================================================Stu();Stu(std::string name,int age, AA *p_temp);//==========================================================Stu(const Stu &s);//==========================================================
Stu &operator=(const Stu &s);//==========================================================Stu(Stu &&s)noexcept;//==========================================================
Stu &operator=(Stu &&s)noexcept;//==========================================================~Stu();//==========================================================//==========================================================
Stu &operator&&(const Stu &s);//==========================================================};
2.2 test/Student.cpp
#include"Student.h"//=================================================================================Stu::Stu(){
name ="s1";
age =1;// TODO s1是空指针,虽然没有new,但是析构函数可以用delete,因为会判断是否为空
std::cout << name <<" "<< age <<" "<<"执行了无参构造函数!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<"空指针没有指向,不能解引用操作"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;};Stu::Stu(std::string name,int age, AA *p_temp){this->name ="s2";// 没有用name赋值,是为了显示this->age =2;// 没有用age赋值,是为了显示
point =newint(888);
std::cout <<this->name <<" "<<this->age <<" "<<"执行了有参构造函数!"<< std::endl;
std::cout <<this->name <<" "<<this->age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout <<this->name <<" "<<this->age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout <<this->name <<" "<<this->age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;
p_internal =newAA(name);// TODO 1.指向内部生成的内部对象,要在析构函数里面先释放后置空;if(p_temp ==nullptr){
p_external =nullptr;}else{
p_external = p_temp;// TODO 2.指向外部传递的外部对象,不用在析构函数里面管理;
p_temp =nullptr;// 防止两个指针指向同一块内存}};//=================================================================================Stu::Stu(const Stu &s){
name ="s3";
age =3;if(s.point ==nullptr){
point =nullptr;}else{//开辟新的空间
point =newint();// 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*point =*s.point;// TODO 注意s不能是空指针,比如s1}
std::cout << name <<" "<< age <<" "<<"执行了拷贝构造函数(深拷贝)!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;};//=================================================================================Stu::Stu(Stu &&s)noexcept{// noexcept表明函数或操作不会发生异常,会给编译器更大的优化空间。
name ="s4";
age =4;// 移动赋值运算符函数,那这个s.name和s.age怎么处理的啊if(s.point ==nullptr){
point =nullptr;}else{// s的指向的地址赋值给当前对象this
point = s.point;// s需要置空,断开指向,避免2个指针指向同一块空间
s.point =nullptr;}
std::cout << name <<" "<< age <<" "<<"执行了移动构造函数!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;};//=================================================================================
Stu &Stu::operator=(const Stu &s){
name ="s5";
age =5;if(s.point ==nullptr){
point =nullptr;}else{//开辟新的空间
point =newint();// 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*point =*s.point;// TODO 注意s不能是空指针,比如s1}
std::cout << name <<" "<< age <<" "<<"执行了拷贝赋值运算符函数!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;return*this;};//=================================================================================
Stu &Stu::operator=(Stu &&s)noexcept{// noexcept表明函数或操作不会发生异常,会给编译器更大的优化空间。
name ="s6";
age =6;// 移动赋值运算符函数,那这个s.name和s.age怎么处理的啊if(s.point ==nullptr){
point =nullptr;}else{// s的指向的地址赋值给当前对象this
point = s.point;// s需要置空,断开指向,避免2个指针指向同一块空间
s.point =nullptr;}
std::cout << name <<" "<< age <<" "<<"执行了移动赋值运算符函数!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;return*this;};//=================================================================================Stu::~Stu(){delete point;
point =nullptr;
std::cout << name <<" "<< age <<" "<<"执行了析构函数!"<< std::endl;delete p_internal;
p_internal =nullptr;};//=================================================================================//**********************************************************************************
Stu &Stu::operator&&(const Stu &s){// 重新定义了&&运算符(DIY)
name ="s9";
age =9;if(s.point ==nullptr){
point =nullptr;}else{//开辟新的空间
point =newint();// 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*point =*s.point;// TODO 注意s不能是空指针,比如s1}
std::cout << name <<" "<< age <<" "<<"执行了拷贝赋值运算符函数!"<< std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址:"<< point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针指向的地址的内容:"<<*point << std::endl;
std::cout << name <<" "<< age <<" "<<"指针自身的地址:"<<&point << std::endl;
std::cout <<"----------------------------------"<< std::endl;return*this;};//**********************************************************************************
------------------------------------------------1.设置六个函数的参数,先让函数运行起来1.1 test/Student.h#include <iostream>class Stu {private: std::string name = "无名氏"; int age = 18;public: Stu(); Stu(std::string name, int age); Stu(cons