• 20240416,深拷贝&浅拷贝,对象初始化和清理,对象模型和THIS指针


     哈哈哈乌龟越狱了

    目录

    2.5 深拷贝&浅拷贝

    2.6 初始化列表

    2.7 类对象作为类成员

    2.8 静态成员

    2.9 成员变量和成员函数分开存储

    2.10 THIS指针的用途

    2.11 空指针访问成员函数

    2.12 COSNT修饰成员函数

    2.5 深拷贝&浅拷贝

    浅拷贝:简单的赋值拷贝炒作
    深拷贝:在堆区重新申请空间进行拷贝操作

    浅拷贝带来的问题就是堆区的内存重复释放;深拷贝是?拷贝的时候重新申请一块内存,记录的数据是一样的,指向的内存是不一样的?

    20240411,内存分区模型,new-delete语句-CSDN博客(一些根本不复习学了就忘还找不到笔记人士,乐,还好学的不多?/不是)

    如果属性在堆区开辟的,一定要自己构造深拷贝函数避免出现问题

    1. #include<iostream>
    2. using namespace std;
    3. class Person
    4. {
    5. public:
    6. int m_age;
    7. int* m_height;//指针接收
    8. Person()
    9. {
    10. cout << "Persong 默认构造 函数的调用" << endl;
    11. }
    12. Person(int age,int height)
    13. {
    14. m_age = age;
    15. m_height=new int(height);//把身高创建在堆区,new返回的是该数据类型的指针
    16. cout << "Persong 有参构造 函数的调用" << endl;
    17. }
    18. //系统提供的拷贝函数是浅拷贝
    19. //自己写一个深拷贝构造函数,解决深拷贝带来的问题
    20. Person(const Person &p)
    21. {
    22. m_age = p.m_age;
    23. //m_height = p.m_height;编译器写的
    24. m_height = new int(*p.m_height);
    25. //在堆区申请一块区域,记录*p_height的内容,即,在堆区创建数据*p_hright
    26. //此时new int(height)没有释放
    27. cout << "Persong 拷贝构造 函数的调用" << endl;
    28. }
    29. ~Person()
    30. {
    31. if (m_height != NULL)
    32. {
    33. delete m_height;//释放
    34. m_height = NULL;//初始化
    35. }
    36. cout << "Persong 默认析构 函数的调用" << endl;//将堆区开辟的数据做释放操作
    37. }
    38. };
    39. void test01()
    40. {
    41. Person p1(28,180);//执行了一次析构函数,指针指向的内存已经被释放掉了
    42. cout << "p1的年龄为" << p1.m_age <<"身高为"<<*p1.m_height << endl;
    43. Person p2(p1);
    44. //拷贝了m_height记录的地址,此时m_height不为空,
    45. //但是地址指向的地方已经被释放了,再进行一次释放,非法操作
    46. cout << "p2的年龄为" << p2.m_age << "身高为" << *p2.m_height << endl;
    47. //函数结束一起释放
    48. }
    49. int main()
    50. {
    51. test01();
    52. system("pause");
    53. return 0;
    54. }
    2.6 初始化列表

    构造函数():属性1(值 1),属性2(值2)···{ }
    构造函数(int a ,int b ,```):属性1(a),属性2(b)···{ }

    1. #include<iostream>
    2. using namespace std;
    3. class Person
    4. {
    5. public:
    6. int m_a;
    7. int m_b;
    8. int m_c;
    9. Person () :m_a(10), m_b(20), m_c(30) {}//不能修改数值
    10. Person(int a, int b, int c) :m_a(a),m_b(b),m_c(c){}//可以修改
    11. };
    12. void test01()
    13. {
    14. Person p;
    15. Person p1(540, 23, 45);//int a=540,m_a(a)
    16. cout << p.m_a << "\t" << p.m_b << "\t" << p.m_c << endl;
    17. cout << p1.m_a << "\t" << p1.m_b << "\t" << p1.m_c << endl;
    18. }
    19. int main()
    20. {
    21. test01();
    22. system("pause");
    23. return 0;
    24. }
    2.7 类对象作为类成员

    俺的BUG:没有特意创建一个子对象,无法输出被嵌套的子对象
    构造和析构的顺序相反

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. class Phone
    5. {
    6. public:
    7. string m_Pname;
    8. Phone(string Pname)
    9. {
    10. m_Pname = Pname;
    11. cout << "Phone的 构造函数 调用" << endl;
    12. }
    13. ~Phone()
    14. {
    15. cout << "Phone的 析构函数 调用" << endl;
    16. }
    17. };
    18. class Person
    19. {
    20. public:
    21. string m_Name;
    22. Phone m_Phone;
    23. Person(string name, string phone) :m_Name(name), m_Phone(phone)
    24. {
    25. cout << "Person的 构造函数 调用" << endl;
    26. }
    27. ~Person()
    28. {
    29. cout << "Person的 析构函数 调用" << endl;
    30. }//先释放PERSON的,再释放PHONE的
    31. };
    32. void test01()
    33. {
    34. Person p("张三", "华为p60");
    35. cout << p.m_Name << endl;//先构造了一个Phone类,先调用了PHONE的构造函数,再PERSON的构造函数
    36. //cout << p.m_Name << "拿了" << p.m_Phone << endl;//编译错误
    37. //说没有 操作数 能匹配<<的运算符
    38. }
    39. int main()
    40. {
    41. test01();
    42. system("pause");
    43. return 0;
    44. }
    2.8 静态成员

    静态成员变量:所有对象共享同一份数据,编译阶段分配内存,类内声明,类外初始化
    静态成员函数:所有对象共享同一个函数,静态成员函数只能访问静态成员变量

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. class Person
    5. {
    6. public:
    7. //(全局?共享),编译分配,类内声明&类外初始化(否则无法访问)
    8. static int m_a;
    9. int m_c;
    10. static void func()
    11. {
    12. m_a = 999;
    13. //m_c = 888;//静态成员函数只能访问静态成员变量 因为所有对象共享,无法区分m_c属于哪一个对象?
    14. cout << "静态成员函数 func() 的调用" << endl;
    15. }
    16. private:
    17. //静态成员变量,函数 也有访问权限
    18. static int m_b;
    19. static void func2()
    20. {
    21. cout << "private 静态成员函数 func() 的调用" << endl;
    22. }
    23. };
    24. //类外初始化,初始化了之后,没有修改的情况下,就是100
    25. int Person::m_a = 100;
    26. int Person::m_b = 300;
    27. void test01()
    28. {
    29. Person p;
    30. cout << p.m_a << endl;//无法解析的外部符号
    31. Person p2;
    32. cout << p2.m_a << endl;//通过对象访问
    33. p2.m_a = 200;
    34. cout << p2.m_a << endl;
    35. cout << p.m_a << endl;//输出200,P和P1共享这一个静态变量
    36. }
    37. void test02()
    38. {
    39. //静态成员变量,不属于某个对象上,所有对象共享同一份数据
    40. //两种访问方式:通过对象,通过类名
    41. cout << Person::m_a << endl;
    42. //cout << Person::m_b << endl;//m_b是私有作用域,不能类外访问
    43. }
    44. void test03()
    45. {
    46. //静态成员函数访问:对象,类名
    47. Person::func();
    48. Person p,p1;
    49. p.func();
    50. p1.func();
    51. //Person::func2();无权限
    52. }
    53. int main()
    54. {
    55. test02();//输出100
    56. cout << endl;
    57. test01();
    58. cout << endl;
    59. test02();//输出200
    60. cout << endl;
    61. test03();
    62. test02();
    63. system("pause");
    64. return 0;
    65. }
    2.9 成员变量和成员函数分开存储

    只有非静态的变量才在对象上

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. class Person
    5. {
    6. };
    7. class Pers
    8. {
    9. int m_a;
    10. int m_b;
    11. static int m_c;//不属于类的对象上
    12. void func(){}//
    13. static void func2(){}//
    14. };
    15. int Pers::m_c = 800;
    16. void test01()
    17. {
    18. Person p;
    19. cout << "size of Person p=" << sizeof(p) << endl;
    20. //空对象占用内存 1
    21. //C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
    22. //(区分不同的空对象)每个空对象也应该有一个独一无二的内存地址
    23. }
    24. void test02()
    25. {
    26. Pers p;
    27. cout << "size of Pers p=\t" << sizeof(p) << endl;//内存对齐成员变量
    28. }
    29. int main()
    30. {
    31. test01();
    32. test02();
    33. system("pause");
    34. return 0;
    35. }
    2.10 THIS指针的用途

    每一个非静态成员函数只会诞生一份函数实例,也就是多个同类型的对象会公用一块代码,this指针指向被调用的成员函数所属的对象
    THIS指针是隐含每一个非静态成员函数内的一种指针,不需要定义,直接使用
    用途:当形参和成员变量同名时,可以用THIS指针来区分;在类的非静态成员函数中返回对象本身,可以使用 RETURN *THIS

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. //解决名称冲突
    5. class Person
    6. {
    7. public:
    8. int age;
    9. Person(int age)
    10. {
    11. //age = age;//编译器认为三个age是同一个,没有和成员变量区分开
    12. this->age = age;//this指针指向被调用的成员函数所属的对象
    13. }
    14. void Personaddage(Person& p)
    15. {
    16. this->age += p.age;//两个变量的AGE相加 || 一个变量的AGE累加
    17. }
    18. //用引用来接收
    19. Person& Personaddage1(Person& p)
    20. {
    21. this->age += p.age;//两个变量的AGE相加 || 一个变量的AGE累加
    22. return *this;//返回对象本身
    23. }
    24. Person Personaddage2(Person& p)
    25. {//返回值
    26. this->age += p.age;
    27. return *this;
    28. }
    29. };
    30. void test01()
    31. {
    32. Person p1(18);
    33. cout << "p1的年龄是 " << p1.age << endl;
    34. }
    35. void test02()
    36. {
    37. Person p(80);
    38. p.Personaddage(p);
    39. cout << "p的年龄是 " << p.age << endl;
    40. Person p1(2);
    41. p.Personaddage(p1);
    42. cout << "p的年龄是 " << p.age << endl;
    43. //p.Personaddage(p1).Personaddage(p1).Personaddage(p1).Personaddage(p1);
    44. //超级连加,错误,第一次函数运算完成,返回一个VOID
    45. p.Personaddage1(p1).Personaddage1(p1).Personaddage1(p1).Personaddage1(p1);//链式编程思想
    46. cout << "p的年龄是 " << p.age << endl;
    47. p.Personaddage2(p1).Personaddage2(p1).Personaddage2(p1).Personaddage2(p1);//链式编程思想
    48. //只运算了第一次,值返回就是?复制一份?和本体值相同,但是不是本体了
    49. cout << "p的年龄是 " << p.age << endl;
    50. }
    51. int main()
    52. {
    53. test01();
    54. test02();
    55. system("pause");
    56. return 0;
    57. }
    2.11 空指针访问成员函数

    C++中空指针也是可以调用成员函数,但是也要注意有么有用到THIS指针
    如果用到,需要加以判断保证代码的健壮性?

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. //解决名称冲突
    5. class Person
    6. {
    7. public:
    8. int m_age;
    9. void showPersonName()
    10. {
    11. cout << "this is Person Class" << endl;
    12. }
    13. void showPersonAge()
    14. {
    15. if (this == NULL)
    16. {
    17. return;//不会走到下一步
    18. }
    19. cout << "m_age=" << m_age << endl;
    20. //cout << "m_age=" << this->m_age << endl;但是this现在是一个空指针,
    21. }
    22. };
    23. void test01()
    24. {
    25. Person* p = NULL;
    26. p->showPersonName();
    27. //p->showPersonAge();//报错
    28. }
    29. int main()
    30. {
    31. test01();
    32. system("pause");
    33. return 0;
    34. }
    2.12 COSNT修饰成员函数

    成员函数后加CONST后-》常函数;常函数不可以修改成员属性,成员属性声明时加关键字MUTABLE后,常函数中依然可修改
    在成员函数后加CONST,本质上修饰的时THIS指针,让指针指向的值也不可修改
    常对象:声明对象前加CONST,常对象只能调用常函数

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. //解决名称冲突
    5. class Person
    6. {
    7. public:
    8. int m_age;//不能直接设置一个初始值,反而会报错受用未初始化的内存p
    9. mutable int m_b;//特殊变量,常函数中也可以修改
    10. void showage()const//(const) Person *const this
    11. //在成员函数后加CONST,本质上修饰的时THIS指针,让指针指向的值也不可修改
    12. {
    13. //m_age = 100;不可修改
    14. //this->m_age = 100;
    15. //this 指针的本质,指针常量,指针的指向不可修改,Person *const this
    16. //this = NULL;不可修改
    17. cout << "m_age=" << m_age << endl;
    18. m_b = 232;
    19. cout << "m_b=" << m_b << endl;//特殊变量可以修改
    20. }
    21. void func(){}
    22. };
    23. void test01()
    24. {
    25. Person p;
    26. p.showage();
    27. }
    28. void test02()
    29. {
    30. const Person p;//常对象
    31. //p.m_age = 1000;//不可修改
    32. p.m_b = 454;//可以修改
    33. p.showage();//常对象只能调用常函数
    34. //p.func();//不可以调用普通成员函数,因为普通成员函数可以修改属性
    35. }
    36. int main()
    37. {
    38. test01();
    39. system("pause");
    40. return 0;
    41. }

  • 相关阅读:
    vue使用carousel(走马灯)开发轮播图
    三面:请设计一个虚拟DOM算法吧
    man 获得帮助信息
    Android通过RecyclerView实现手风琴效果
    python socket编程3 - socket的选项
    07 _ 链表(下):如何轻松写出正确的链表代码?
    【墨染】找特有姿态!基于【灵茶山艾府】题解的补充图解
    第十九章总结
    (swjtu西南交大)数据库实验(概念数据库设计及逻辑关系转换):音乐软件数据管理系统
    labelme标注的json、coco格式快速转yolo格式
  • 原文地址:https://blog.csdn.net/qq_51583806/article/details/137800346