欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

C++类的六个特殊成员函数20220226

时间:2023-04-30
------------------------------------------------ 1.设置六个函数的参数,先让函数运行起来 1.1 test/Student.h

#include 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 #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 //--------------------------------------------------------------------------------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_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; };};//--------------------------------------------------------------------------------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的指向的地址赋值给当前对象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 = 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的指向的地址赋值给当前对象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 = 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 #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 指针指向的地址:0s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作s1 1 指针自身的地址:0x7ffdf188c3c8----------------------------------s2 2 执行了有参构造函数!s2 2 指针指向的地址:0x1908050s2 2 指针指向的地址的内容:888s2 2 指针自身的地址:0x7ffdf188c408----------------------------------内部对象 执行了无参构造函数!内部对象 指针指向的地址:0x19080a0内部对象 指针指向的地址的内容:666内部对象 指针自身的地址:0x1908090----------------------------------s3 3 执行了拷贝构造函数(深拷贝)!s3 3 指针指向的地址:0x19080c0s3 3 指针指向的地址的内容:888s3 3 指针自身的地址:0x7ffdf188c448----------------------------------s4 4 执行了移动构造函数!s4 4 指针指向的地址:0x19080c0s4 4 指针指向的地址的内容:888s4 4 指针自身的地址:0x7ffdf188c488----------------------------------s1 1 执行了无参构造函数!s1 1 指针指向的地址:0s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作s1 1 指针自身的地址:0x7ffdf188c4c8----------------------------------s5 5 执行了拷贝赋值运算符函数!s5 5 指针指向的地址:0x19080e0s5 5 指针指向的地址的内容:888s5 5 指针自身的地址:0x7ffdf188c4c8----------------------------------s1 1 执行了无参构造函数!s1 1 指针指向的地址:0s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作s1 1 指针自身的地址:0x7ffdf188c508----------------------------------s6 6 执行了移动赋值运算符函数!s6 6 指针指向的地址:0x19080e0s6 6 指针指向的地址的内容:888s6 6 指针自身的地址:0x7ffdf188c508----------------------------------s1 1 执行了无参构造函数!s1 1 指针指向的地址:0s1 1 指针指向的地址的内容:空指针没有指向,不能解引用操作s1 1 指针自身的地址:0x7ffdf188c548----------------------------------s9 9 执行了拷贝赋值运算符函数!s9 9 指针指向的地址:0x1908100s9 9 指针指向的地址的内容:888s9 9 指针自身的地址:0x7ffdf188c548----------------------------------s9 9 执行了拷贝赋值运算符函数!s9 9 指针指向的地址:0x1908120s9 9 指针指向的地址的内容:888s9 9 指针自身的地址:0x7ffdf188c548----------------------------------s9 9 执行了拷贝赋值运算符函数!s9 9 指针指向的地址:0x1908140s9 9 指针指向的地址的内容:888s9 9 指针自身的地址:0x7ffdf188c548----------------------------------s9 9 执行了拷贝赋值运算符函数!s9 9 指针指向的地址:0x1908160s9 9 指针指向的地址的内容:888s9 9 指针自身的地址:0x7ffdf188c548----------------------------------=======================================执行了main函数s9 9 执行了析构函数!s6 6 执行了析构函数!s5 5 执行了析构函数!s4 4 执行了析构函数!s3 3 执行了析构函数!s2 2 执行了析构函数!内部对象 执行了析构函数!s1 1 执行了析构函数!外部对象 执行了析构函数!Process finished with exit code 0

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。