------------------------------------------------

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(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 这个必须要加int main() {// 类的六个特殊成员函数总结如下:// 普通构造函数(无参构造函数: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;return 0;
}

1.4 输出结果

/home/liuhao/CLionProjects/Robot_modules_cpp/cmake-build-debug/bin/class_function
执行了无参构造函数!
执行了有参构造函数!
执行了拷贝构造函数!
执行了移动构造函数!
执行了无参构造函数!
执行了拷贝赋值运算符函数!
执行了无参构造函数!
执行了移动赋值运算符函数!执行了main函数执行了析构函数!
执行了析构函数!
执行了析构函数!
执行了析构函数!
执行了析构函数!
执行了析构函数!Process finished with exit code 0

------------------------------------------------

2.六个函数的具体功能实现

2.1 test/Student.h

#include <iostream>//--------------------------------------------------------------------------------
class AA {private:std::string name = "";int *AA_d = nullptr;public:explicit AA(std::string name) {      // 单一参数的构造函数最好加上explicit,避免隐式转换this->name = name;AA_d = new int(666);        // TODO 这里要给定指向,因为后面有*AA_dstd::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;};
};
//--------------------------------------------------------------------------------class Stu {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 = new int(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 = new AA(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 = new int();      // 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*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的指向的地址赋值给当前对象thispoint = 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 = new int();      // 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*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的指向的地址赋值给当前对象thispoint = 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 = new int();      // 不要使用浅拷贝(存在动态成员的隐患),尽量使用深拷贝//把原来的值,拷贝过来。*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;
};
//**********************************************************************************

2.3 test/C++类的六个特殊成员函数.cpp

#include <iostream>#include "Student.h"     // TODO 这个必须要加int main() {// 类的六个特殊成员函数总结如下:// 普通构造函数(无参构造函数:Stu()、有参构造函数:Stu(std::string name, int age, AA *p_temp))// 拷贝构造函数:Stu(const Stu &s)// 移动构造函数:Stu(Stu &&s)// 拷贝赋值运算符函数:Stu &operator=(const Stu &s)// 移动赋值运算符函数:Stu &operator=(Stu &&s)// 析构函数:~Stu()//=================================================================================AA aa("外部对象");//=================================================================================Stu s1;                         // 无参构造函数,里面有空指针;Stu s2("内部对象", 100, &aa);    // 有参构造函数//=================================================================================Stu s3 = s2;                    // 拷贝构造函数(深拷贝)        // 不能用s1,里面有空指针呢;//=================================================================================Stu s4 = std::move(s3);              // 移动构造函数               // 不能用s1,里面有空指针呢;
//    // TODO s3竟然还可以再用
//    std::cout << "**************** " << s3.point << std::endl;      // 0
//    std::cout << "**************** " << s3.name << std::endl;       // s3
//    std::cout << "**************** " << s3.age << std::endl;        // 3//=================================================================================Stu s5;s5 = s4;                        // 拷贝赋值运算符函数          // 不能用s1,里面有空指针呢;//=================================================================================Stu s6;s6 = std::move(s5);                  // 移动赋值运算符函数        // 不能用s1,里面有空指针呢;
//    // TODO s5竟然还可以再用
//    std::cout << "**************** " << s5.point << std::endl;      // 0
//    std::cout << "**************** " << s5.name << std::endl;       // s4
//    std::cout << "**************** " << s5.age << std::endl;        // 4//=================================================================================Stu s9;s9 && s6;                       // 重新定义了&&运算符(DIY)s9 && s6 && s4 && s2;           // 运算符多次重载
//    s9 && s6 && s3 && s2 && s1;   // s1里面有空指针,不能参与运算符多次重载,因为operator&&函数里面有解引用操作//=================================================================================std::cout << "=======================================执行了main函数" << std::endl;return 0;
}

2.4 输出结果

/home/liuhao/CLionProjects/Robot_modules_cpp/cmake-build-debug/bin/class_function
外部对象 执行了无参构造函数!
外部对象 指针指向的地址:0x1907c20
外部对象 指针指向的地址的内容:666
外部对象 指针自身的地址:0x7ffdf188c390
----------------------------------
s1 1 执行了无参构造函数!
s1 1 指针指向的地址:0
s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作
s1 1 指针自身的地址:0x7ffdf188c3c8
----------------------------------
s2 2 执行了有参构造函数!
s2 2 指针指向的地址:0x1908050
s2 2 指针指向的地址的内容:888
s2 2 指针自身的地址:0x7ffdf188c408
----------------------------------
内部对象 执行了无参构造函数!
内部对象 指针指向的地址:0x19080a0
内部对象 指针指向的地址的内容:666
内部对象 指针自身的地址:0x1908090
----------------------------------
s3 3 执行了拷贝构造函数(深拷贝)!
s3 3 指针指向的地址:0x19080c0
s3 3 指针指向的地址的内容:888
s3 3 指针自身的地址:0x7ffdf188c448
----------------------------------
s4 4 执行了移动构造函数!
s4 4 指针指向的地址:0x19080c0
s4 4 指针指向的地址的内容:888
s4 4 指针自身的地址:0x7ffdf188c488
----------------------------------
s1 1 执行了无参构造函数!
s1 1 指针指向的地址:0
s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作
s1 1 指针自身的地址:0x7ffdf188c4c8
----------------------------------
s5 5 执行了拷贝赋值运算符函数!
s5 5 指针指向的地址:0x19080e0
s5 5 指针指向的地址的内容:888
s5 5 指针自身的地址:0x7ffdf188c4c8
----------------------------------
s1 1 执行了无参构造函数!
s1 1 指针指向的地址:0
s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作
s1 1 指针自身的地址:0x7ffdf188c508
----------------------------------
s6 6 执行了移动赋值运算符函数!
s6 6 指针指向的地址:0x19080e0
s6 6 指针指向的地址的内容:888
s6 6 指针自身的地址:0x7ffdf188c508
----------------------------------
s1 1 执行了无参构造函数!
s1 1 指针指向的地址:0
s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作
s1 1 指针自身的地址:0x7ffdf188c548
----------------------------------
s9 9 执行了拷贝赋值运算符函数!
s9 9 指针指向的地址:0x1908100
s9 9 指针指向的地址的内容:888
s9 9 指针自身的地址:0x7ffdf188c548
----------------------------------
s9 9 执行了拷贝赋值运算符函数!
s9 9 指针指向的地址:0x1908120
s9 9 指针指向的地址的内容:888
s9 9 指针自身的地址:0x7ffdf188c548
----------------------------------
s9 9 执行了拷贝赋值运算符函数!
s9 9 指针指向的地址:0x1908140
s9 9 指针指向的地址的内容:888
s9 9 指针自身的地址:0x7ffdf188c548
----------------------------------
s9 9 执行了拷贝赋值运算符函数!
s9 9 指针指向的地址:0x1908160
s9 9 指针指向的地址的内容:888
s9 9 指针自身的地址:0x7ffdf188c548
----------------------------------
=======================================执行了main函数
s9 9 执行了析构函数!
s6 6 执行了析构函数!
s5 5 执行了析构函数!
s4 4 执行了析构函数!
s3 3 执行了析构函数!
s2 2 执行了析构函数!
内部对象 执行了析构函数!
s1 1 执行了析构函数!
外部对象 执行了析构函数!Process finished with exit code 0

C++类的六个特殊成员函数20220226相关推荐

  1. 继承和多态 2.0 -- 继承的六个默认成员函数

    本文重要介绍普通继承中如何写派生类的六个默认成员函数,主要是针对在派生类中,如何调用基类的六个默认成员函数 需要说明的一点就是,如果子类中没有调用父类的函数时,系统会自动生成一个. 构造函数 子类中有 ...

  2. 【C++】类和对象【中篇】--C++六个默认成员函数以及const成员函数

    文章目录 一.类的6个默认成员函数 二.构造函数 1.概念 2.特性 2.1特征分析--自动生成 2.2.特征分析--选择处理 2.3特征分析--默认构造 3.C++11补丁--缺省值 三.析构函数 ...

  3. 【C++】类和对象的默认成员函数讲解

    文章目录 简介 构造函数※※※ 系统生成的默认构造函数的特性 构造函数的初始化列表 析构函数※ 拷贝构造函数※※※ 默认的拷贝构造函数 赋值重载函数 赋值运算符的重载格式 赋值运算符只能重载成类的成员 ...

  4. [c++ 简单的笔记] 类的6个默认成员函数

    -客亦知夫水与月乎? -哀吾生之须臾 羡长江之无穷. 文章目录 类的6个默认成员函数 构造函数 构造函数初始化列表 注意 explicit关键字(了解) 拷贝构造函数 务必自己写深拷贝的情况的情况 赋 ...

  5. boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回调测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回调测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回 ...

  6. 3-3:类与对象中篇——默认成员函数之构造函数和析构函数

    文章目录 一:类的默认6个成员函数 二:构造函数 (1)构造函数的概念 (2)构造函数注意事项 三:析构函数 (1)析构函数的概念 (2)析构函数注意事项 一:类的默认6个成员函数 如果一个类里面什么 ...

  7. 【 C++ 】类和对象(中)—— 类的6个默认成员函数

    目录 1.类的6个默认成员函数 2.构造函数 构造函数概念 构造函数特性 3.析构函数 析构函数概念 析构函数特性 4.拷贝构造函数 拷贝构造函数概念 拷贝构造函数特性 5.赋值运算符重载 运算符重载 ...

  8. 类与对象:类的6个默认成员函数: 构造函数、析构函数、拷贝构造函数、赋值操作符重载、默认拷贝构造与赋值运算符重载的问题、const成员函数、 取地址及const取地址操作符重载

    1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类.任何一个类在我们不写的情况下,都会自动生成下面6个默认成员函数. 构造函数 析构函数 拷贝构造函数 赋值操作符重载 const成员函数 ...

  9. C++类与对象(二) 六个默认成员函数

    目录 1.构造函数 (1)引入 (2)性质与验证 (3)总结 2.析构函数 (1)概念 (2)性质与验证 (3)总结 3拷贝构造函数 (1)概念 (2)性质与验证 (3)总结 4.赋值运算符重载 (1 ...

最新文章

  1. 用SNMP实现对大型网络的轻松管理!
  2. r语言 分类变量 虚拟变量_R语言中的变量
  3. centos 6.5 安装redis
  4. 企业正确进行数字化转型的7个秘诀
  5. 如何在JavaScript中大写字符串的首字母
  6. 登陆注册重连 之 老掉牙的故事 新说法
  7. python数据字典排序_Python自动处理数据字典(Python是3.6版本)
  8. bzoj1577 [Usaco2009 Feb]庙会捷运Fair Shuttle
  9. webpack 代理问题
  10. 手机斗鱼服务器无响应,win7看斗鱼直播很卡怎么办|win7斗鱼未响应的解决方法
  11. meanshift跟踪算法
  12. 如何用c语言实现猜数字游戏?
  13. LabVIEW自动整理程序框图
  14. 用python画一个机器猫歌词_用Python语言模型和LSTM做一个Drake饶舌歌词生成器
  15. SCRIPT1004: 缺少 ‘;‘IE8浏览器报错
  16. 如何利用SQL注入进行爆库
  17. 计算机网络第一章笔记呕心沥血之作 值得收藏
  18. 实战|Python爬取字节跳动1W+招聘信息
  19. 人体姿态识别-pose estimation
  20. Ubuntu-Base 18 文件系统 在iMX8平台上的移植

热门文章

  1. Adobe登陆出现Access denied解决方法
  2. 方向比努力重要,能力比知识重要,健康比成绩重要,生活比文凭重要,情商比智商重要
  3. 要命!《程序员延寿指南》火爆 GitHub,日涨1500+星,跟着码农干多活 20 年
  4. ArcMap:线、面符号的制作(通用线符号的制作)超详细
  5. bean是什么,bean和javabean
  6. PPT页码插入(PPT页码不显示)
  7. 传奇黑客成『吹哨人』,推特麻烦了;谷歌20+技术学习路线;Python数据科学电子书;游戏智能体开发平台;前沿论文 | ShowMeAI资讯日报
  8. java 多线程的三种写法
  9. 矩阵分析_1 线性方程组解与列向量组的关系
  10. Python《机器学习实战》读书笔记(三)——决策树