• C++基础知识(五)--- 智能指针类&字符串类


    目录

    一. 智能指针类(重点)

    指针运算符的重载

    二. 仿函数

    三. 其他重载

    四. 字符串类(了解)


    一. 智能指针类(重点)

    作用:管理另一个类的对象的释放。

    怕你忘记delete导致内存泄漏,所以搞了个智能指针。

    1. class Maker
    2. {
    3. public:
    4. Maker()
    5. {
    6. cout << "无参构造" << endl;
    7. }
    8. void printMaker()
    9. {
    10. cout << "hello Maker" << endl;
    11. }
    12. ~Maker()
    13. {
    14. cout << "析构函数" << endl;
    15. }
    16. };
    17. class SmartPoint
    18. {
    19. public:
    20. SmartPoint(Maker* m)
    21. {
    22. this->pMaker = m;
    23. }
    24. ~SmartPoint()
    25. {
    26. if (this->pMaker != NULL)
    27. {
    28. cout << "SmartPoint析构函数" << endl;
    29. delete this->pMaker;
    30. this->pMaker = NULL;
    31. }
    32. }
    33. private:
    34. Maker* pMaker;
    35. };
    36. void test01()
    37. {
    38. Maker* p = new Maker; //这里的Maker不是在栈区,test函数结束时,如果不写delete,这里是不会被释放的
    39. SmartPoint sm(p); //这里局部变量是在栈区,test函数结束时是会调用其析构函数释放空间的
    40. //在它的析构函数中delete了Maker的对象,会调用到Maker的析构函数。
    41. }

     

    指针运算符的重载

    1. Maker* operator->()
    2. {
    3. return this->pMaker;
    4. }
    5. Maker& operator*()
    6. {
    7. return *pMaker; //返回一个对象,所以用引用
    8. }
    9. void test()
    10. {
    11. Maker* m = new Maker;
    12. Point p(m);
    13. p->printMaker(); p-> 在这里等价于 pMaker->
    14. (*p).printMaker();
    15. }

    二. 仿函数

    一个类如果重载了函数调用符号,那么这个类实例化出的对象也叫仿函数。

    1. class Maker
    2. {
    3. public:
    4. Maker()
    5. {
    6. cout << "构造函数" << endl;
    7. name = "sun";
    8. }
    9. void printMaker()
    10. {
    11. cout << "name:" << name+" handsome" << endl;
    12. }
    13. void operator()()
    14. {
    15. cout << "hello" << endl;
    16. }
    17. void operator()(int a,int b)
    18. {
    19. cout << a + b << endl;
    20. }
    21. ~Maker()
    22. {
    23. cout << "析构函数" << endl;
    24. }
    25. public:
    26. string name;
    27. int a;
    28. };
    29. void test()
    30. {
    31. Maker func;
    32. func(); //看起来像函数,其实是对象
    33. func.printMaker();
    34. func(1, 2);
    35. }

    输出为:

    1. 构造函数
    2. hello
    3. name:sun handsome
    4. 3
    5. 析构函数

    三. 其他重载

    重载 bool,!

    1. class Maker
    2. {
    3. public:
    4. Maker()
    5. {
    6. a = 0;
    7. }
    8. void SetA(int val)
    9. {
    10. a = val;
    11. }
    12. //没有返回值,也没有void
    13. operator bool()
    14. {
    15. if (a <= 0)
    16. return false;
    17. else
    18. return true;
    19. }
    20. bool operator!()
    21. {
    22. if (a <= 0)
    23. return true;
    24. else
    25. return false;
    26. }
    27. public:
    28. int a;
    29. };
    30. void test()
    31. {
    32. Maker m;
    33. m.SetA(10);
    34. if (m)
    35. cout << "true" << endl;
    36. else
    37. cout << "false" << endl;
    38. if (!m)
    39. cout << "false" << endl;
    40. else
    41. cout << "true" << endl;
    42. }

    四. 字符串类(了解)

    1. class MyString
    2. {
    3. friend ostream& operator<<(ostream& out, MyString& str);
    4. friend istream& operator>>(istream& in, MyString& str);
    5. public:
    6. MyString()
    7. {
    8. this->pM = new char[1];
    9. this->pM[0] = '\0';
    10. this->mSize = 0;
    11. }
    12. MyString(int n, char c) //用户可以设定初始字符串,n个c组成的字符串
    13. {
    14. this->pM = new char[n + 1];
    15. for (int i = 0; i < n; i++)
    16. {
    17. this->pM[i] = c;
    18. }
    19. this->pM[n] = '\0';
    20. this->mSize = n;
    21. }
    22. MyString(const MyString& str)
    23. {
    24. this->pM = new char[strlen(str.pM) + 1];
    25. strcpy(this->pM, str.pM);
    26. this->mSize = str.mSize;
    27. }
    28. ~MyString()
    29. {
    30. if (this->pM != NULL)
    31. {
    32. delete[] this->pM;
    33. this->pM = NULL;
    34. }
    35. }
    36. MyString& operator=(const MyString& str)
    37. {
    38. //1.释放原来空间
    39. if (this->pM != NULL)
    40. {
    41. delete[] this->pM;
    42. this->pM = NULL;
    43. }
    44. //2.申请空间
    45. this->pM = new char[strlen(str.pM) + 1];
    46. //3.拷贝数据
    47. strcpy(this->pM, str.pM);
    48. this->mSize = str.mSize;
    49. return *this;
    50. }
    51. MyString operator+(const MyString& str)
    52. {
    53. //MyString s3=s1+s2; this是s1,str是s2
    54. //获取s3要开辟的空间大小
    55. int newlen = this->mSize + str.mSize + 1;
    56. //1.定义一个临时变量
    57. MyString tmp;
    58. //2.释放原来的空间
    59. if (tmp.pM != NULL)
    60. {
    61. delete[] tmp.pM;
    62. tmp.pM = NULL;
    63. }
    64. //3.申请新的空间
    65. tmp.pM = new char[newlen];
    66. memset(tmp.pM, 0, newlen);
    67. tmp.mSize = this->mSize + str.mSize;
    68. //4.追加字符到空间中
    69. strcat(tmp.pM, this->pM);
    70. strcat(tmp.pM, str.pM);
    71. return tmp;
    72. }
    73. MyString operator+(const char* s)
    74. {
    75. int newlen = this->mSize + strlen(s);
    76. char* newspace = new char[newlen + 1];
    77. memset(newspace, 0, newlen + 1);
    78. strcat(newspace, this->pM);
    79. strcat(newspace, s);
    80. MyString tmp;
    81. if (tmp.pM != NULL)
    82. {
    83. delete[] tmp.pM;
    84. tmp.pM = NULL;
    85. }
    86. tmp.pM = newspace;
    87. tmp.mSize = newlen;
    88. return tmp;
    89. }
    90. MyString& operator+=(const MyString& str)
    91. {
    92. //1.获取两个字符串的总字符个数
    93. int newlen = this->mSize + str.mSize;
    94. //2.申请新空间
    95. char* newspace = new char[newlen + 1];
    96. memset(newspace, 0, newlen + 1);
    97. //3.追加数据
    98. strcat(newspace, this->pM);
    99. strcat(newspace, str.pM);
    100. //4.释放本身的空间
    101. if (this->pM != NULL)
    102. {
    103. delete[] this->pM;
    104. this->pM = NULL;
    105. }
    106. this->pM = newspace;
    107. this->mSize = newlen;
    108. return *this;
    109. }
    110. MyString& operator+=(const char* s)
    111. {
    112. //1.获取两个字符串的总字符个数
    113. int newlen = this->mSize + strlen(s);
    114. //2.申请新空间
    115. char* newspace = new char[newlen + 1];
    116. memset(newspace, 0, newlen + 1);
    117. //3.追加数据
    118. strcat(newspace, this->pM);
    119. strcat(newspace, s);
    120. //4.释放本身的空间
    121. if (this->pM != NULL)
    122. {
    123. delete[] this->pM;
    124. this->pM = NULL;
    125. }
    126. this->pM = newspace;
    127. this->mSize = newlen;
    128. return *this;
    129. }
    130. int Size()
    131. {
    132. return this->mSize;
    133. }
    134. char& operator[](int index)
    135. {
    136. return this->pM[index];
    137. }
    138. private:
    139. char* pM;
    140. int mSize;
    141. };
    142. ostream& operator<<(ostream& out, MyString& str)
    143. {
    144. out << str.pM;
    145. return out;
    146. }
    147. istream& operator>>(istream& in, MyString& str)
    148. {
    149. //用户输入的字符串要存储到s4.pM指向的堆区空间
    150. //定义临时空间
    151. char tmp[64] = { 0 };
    152. //获取用户输入的信息
    153. in >> tmp;
    154. //释放s4的空间
    155. if (str.pM != NULL)
    156. {
    157. delete[] str.pM;
    158. str.pM = NULL;
    159. }
    160. //申请新的空间
    161. str.pM = new char[strlen(tmp) + 1];
    162. memset(str.pM, 0, strlen(tmp) + 1);
    163. //拷贝用户输入的信息到堆区空间
    164. strcpy(str.pM, tmp);
    165. str.mSize = strlen(tmp);
    166. return in;
    167. }

     

  • 相关阅读:
    骨传导耳机也有好音质,而且设计还挺潮,南卡Runner Pro 4上手
    django rest framework 学习笔记-实战商城3
    新增MariaDB数据库管理、支持多版本MySQL数据库共存,1Panel开源面板v1.6.0发布
    libvirt vcpu热插拔报错:failed to find appropriate hotpluggable vcpus
    真的,Java并发编程基础入门看这个就够了
    有此秘籍,TIF图片转Excel表格不再难
    美化页面元素
    使用C#根据Windows API判断窗体是否置顶
    【android12-linux-5.1】【ST芯片】【RK3588】【LSM6DSR】HAL移植
    摩尔信使MThings的报文管理功能
  • 原文地址:https://blog.csdn.net/woshizuopie/article/details/125817028