C++ 指针

指针的使用、使用new创建动态数组、使用delete释放内存

  1. #include <iostream>
  2. using namespace std;
  3. // ----------------------------------指针-------------------------------------
  4. void pointer(){
  5. int updates = 6;
  6. int * p_updates;
  7. p_updates = & updates;
  8. cout << "Value:updates = " << updates << endl;
  9. cout << "*p_updates = " << *p_updates << endl;
  10. cout << "Address:&updates = " << &updates << endl;
  11. cout << "p_updates = " << p_updates << endl;
  12. // 程序输出:
  13. // Value:updates = 6
  14. // *p_updates = 6
  15. // Address:&updates = 0xffffcbd4
  16. // p_updates = 0xffffcbd4
  17. // int变量updates和指针变量p_updates只不过是一枚硬币的两面。变量updates表示值,并使用&操作符来获得地址;
  18. // 而变量p_updates表示地址,并使用*操作符来取值,由于p_updates指向updates,因此*p_updates和updates
  19. // 完全等价。可以像使用int变量那样使用*p_updates。
  20. // 指针的定义-*号操作符两边的空格是可选的
  21. int *ptr;
  22. int* psr;
  23. // 每个指针变量的创建都需要一个*,下面的例子将创建一个指针p1和一个int变量p2
  24. int *p1, p2;
  25. // 使用new关键字为指针分配内存
  26. // 在C语言中可以使用库函数malloc()来分配内存,在C++中还有更好的方法——使用new操作符
  27. int *pt = new int;
  28. // 内存耗尽
  29. // 计算机可能会由于没有足够的内存而无法满足new的请求,在这种情况下,new将返回0,在C++中,值为0分指针
  30. // 被称为空指针null pointer,C++确保空值指针不会指向有效的数据,因此它常被用来表示操作符或函数失效,
  31. // 如果成功,将返回一个有用的指针。
  32. // 使用delete来释放内存
  33. // 当需要内存时,可以使用new来请求,这只是C++内存管理数据包中有魅力的一个方面。另一个方面是delete操作符,
  34. // 它使得在使用完内存后,能够将其归还给内存池,这是通向最有效地使用内存的关键一步。归还或释放free的内存可供
  35. // 程序的其他部分使用。使用delete时,后面要加上指向内存块的指针(这些内存块最初是用new分配的)
  36. // **注意:只能用delete来释放使用new分配的内存。不过对空指针使用DELETE是安全的。
  37. // 这将释放ps指向的内存,但不会删除指针ps的本身,例如,可以将ps重新指向另一个新分配的内存块,一定要配对
  38. // 地使用new和delete。否则程序将发生内存泄露memory leak,也就是说,被分配的内存再也无法使用了;如果
  39. // 内存泄露严重,则程序将由于不断寻找更多内存而终止
  40. int *p3 = new int;
  41. delete p3;
  42. // 不要尝试释放已经释放的内存块,C++标准指出,这样做的结果将是不确定的,这意味着什么情况都可能发生。另外
  43. // 不能使用delete来释放声明变量所获得的内存;
  44. // int *p4 = new int;
  45. // delete p4;
  46. // delete p4; //not ok now,不能重复释放已经释放的内存块
  47. // int jugs = 5;
  48. // int *p5 = &jugs;
  49. // delete p5; //不能delete来释放声明变量所获得的内存;
  50. // **注意,使用delete的关键在于,将他用于new分配的内存,这并不意味着要使用用于new的指针,而是用于new的地址
  51. // 一般来说,不要创建两个指向同一个内存块的指针,因为这将增加错误地删除同一个内存块两次的可能性
  52. // int *p6 = new int;
  53. // int *p7 = p6;
  54. // delete = p6;
  55. // 使用new创建动态数组
  56. // 在C++中,创建动态数组很容易,只要将数组的元素类型和元素数目告诉new即可,必须在类型名后加上[],其中包含元素数目
  57. int *psome = new int[10];
  58. // new操作符返回第一个元素的地址,在这个例子中,该地址被赋给指针psome,当程序结束后,应使用DELETE释放
  59. // 指针数组的使用
  60. psome[0] = 0;
  61. psome[1] = 2;
  62. psome[2] = 3;
  63. cout << "psome[0] = " << psome[0] << endl;
  64. cout << "psome[1] = " << psome[1] << endl;
  65. cout << "psome[2] = " << psome[2] << endl;
  66. // psome[0] = 0
  67. // psome[1] = 2
  68. // psome[2] = 3
  69. psome = psome + 1;
  70. cout << "psome[0] = " << psome[0] << endl;
  71. cout << "psome[1] = " << psome[1] << endl;
  72. // psome[0] = 2
  73. // psome[1] = 3
  74. // 指针返回到开始
  75. psome = psome - 1;
  76. // 不能修改数组名的值,但指针是变量,因此可以修改他们的值。将psome + 1的效果,表达式psome[0]现在指向的是
  77. // 数组的第二个值,因此将psome + 1导致它指向第二个元素而不是第一个。将它减一后,指针将指向原来的值
  78. // 在释放new创建的动态数组时,应使用另一种格式的delete,它能够指出所要释放的是一个数组
  79. // []会告诉程序,应释放整个数组,而不仅仅是指针指向的元素
  80. delete[] psome;
  81. // 使用new和delete时,应遵守以下规则:
  82. // 1、不要使用delete来释放不是new分配的内存
  83. // 2、不要使用delete释放同一个内存两次
  84. // 3、如果使用new []为数字分配内存,则应使用delete[]来释放
  85. // 4、如果使用new []为一个实体分配内存,则应使用delete来释放
  86. // 5、对空指针应用delete是安全的
  87. // 将指针变量加一后,其增加的值等于指向类型占用的字节数
  88. // stacks[1]可以看作是* (stacks + 1),这意味着先计算第二个元素的地址,然后找到存储在那里的值。
  89. // 最后输出存储在那里的值。
  90. char flower[10]= "rose";
  91. cout << flower << endl;
  92. cout << &flower << endl;
  93. }
  94. int main() {
  95. pointer();
  96. return 0;
  97. }

使用new创建动态结构、使用delete释放new创建的动态结构的内存、使用->访问指针指向的结构体变量

  1. #include <iostream>
  2. using namespace std;
  3. // 动态结构
  4. void structure(){
  5. struct things{
  6. int good;
  7. int bad;
  8. };
  9. things grubonse = {3, 453};
  10. things *pt = &grubonse;
  11. // 如果结构体标识符是结构名,则使用句点操作符
  12. // 如果标识符是指向结构的指针,则使用箭头操作符
  13. cout << "ps.good = " << pt->good << endl;
  14. cout << "ps.bad = " << pt->bad << endl;
  15. // 使用new创建结构体变量
  16. person *person2 = new person;
  17. person2->name = "fc";
  18. person2->age = 18;
  19. cout << "person2.name = " << person2->name << endl;
  20. cout << "person2.age = " << person2->age << endl;
  21. // 释放使用new创建的动态结构的空间
  22. delete person2;
  23. }
  24. int main() {
  25. structure();
  26. return 0;
  27. }

指针函数的定义、赋值、调用

  1. // 定义指针函数
  2. // 指针函数声明时需要将*和函数名括起来,括号优先级比*操作符高,因此*fun (int)代表返回指针的函数,
  3. // 而(*fun) (int)意味着fun是一个指向函数的指针
  4. double pam(int);
  5. double (*pf) (int);
  6. // 指针函数的赋值,将pam函数的地址赋给pf,赋值函数和指针函数的返回值类型编写相同才能赋值
  7. // pf = pam;
  8. // 指针函数的调用
  9. double x = pam(3);
  10. double y = (*pf)(5);