Advertisement
force1987

delete or nullptr

Mar 26th, 2021
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.97 KB | None | 0 0
  1. #include <iostream>
  2. using namespace std;
  3. struct Lib {
  4. const char* autor = new const char[10];
  5. const char* name = new const char[10];
  6. int pages;
  7. };
  8.  
  9. void showLib(Lib** book) {
  10. int size = _msize(book) / sizeof(book);
  11. for (int i = 0; i < size; i++) {
  12. cout << i << ": ";
  13. cout << "Autor: " << book[i]->autor << "\t";
  14. cout << "Name: " << book[i]->name << "\t";
  15. cout << "Pages: " << book[i]->pages << "\t";
  16. cout << endl;
  17. }
  18. }
  19.  
  20. void addLib(Lib**& book, const char* autor, const char* name, int pages) {
  21. cout << endl << "В функции addLib нам нужно добавить элемент к исходному массиву структур" << endl;
  22.  
  23. int size = _msize(book) / sizeof(book);
  24.  
  25.  
  26.  
  27.  
  28. Lib** stack = new Lib * [size];
  29. for (int i = 0; i < size; i++) {
  30. stack[i] = new Lib{ book[i]->autor,book[i]->name,book[i]->pages };
  31. }
  32. Lib*** root = &stack;
  33. Lib** adrind = &stack[0];
  34. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  35. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  36. const char** adr1 = &(stack[0]->autor);
  37. const char** adr2 = &(stack[0]->name);
  38. int* adr3 = &(stack[0]->pages);
  39. cout << "Структура в свою очередь тоже состоит из 2-х указателей и одного целочисленного значения" << endl;
  40. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение " << *adr1 << endl;
  41. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение " << *adr2 << endl;
  42. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  43. cout << "Для того, чтобы полностью очистить память нам нужно сначала удалить структуры. При удалении одного из элементов структуры удаляется вся структура, включая указатель на неё, но не включая указатели на другие структуры и указатель на массив указателей." << endl;
  44. cout << "Можно было бы удалить указатель на структуру вместе с ней, но в элементах структуры есть массивы const char*, адрес к которым не получается получить напрямую, и чтобы гарантировать их удаление мы используем nullptr для элемента структуры, который будет указателем на этот массив" << endl;
  45. cout << "Будем смотреть, что происходит в памяти на каждом шаге." << endl<<"исходный массив[i]->autor = nullptr;"<<endl;
  46. for (int i = 0; i < size; i++) {
  47.  
  48. root = &book;
  49. adrind = &book[0];
  50. adr1 = &(book[0]->autor);
  51. adr2 = &(book[0]->name);
  52. adr3 = &(book[0]->pages);
  53. book[i]->autor = nullptr;
  54. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  55. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  56. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  57. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение " << *adr2 << endl;
  58. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  59. cout << endl<<"Теперь удаляем delete[]исходный массив[i]->autor"<<endl;
  60.  
  61. book[i]->name = nullptr;
  62. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  63. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  64. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  65. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  66. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  67. cout << "delete[]исходный массив[i]->name;" << endl;
  68.  
  69. delete[]book[i];
  70. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  71. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  72. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  73. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  74. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  75. }
  76. delete[]book;
  77. cout << "delete[]исходный массив" << endl;
  78. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  79. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  80. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  81. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  82. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  83. book = stack;
  84. cout << "В итоге думаю, что команды delete[]имя массива[i]->элемент структуры(указатель) не имеет смысла, т.к.указатель уже никуда не указывает."<<endl;
  85. system("pause");
  86. system("cls");
  87. }
  88.  
  89. void addLib2(Lib**& book, const char* autor, const char* name, int pages) {
  90. cout << endl << "Начнём сначала, но теперь попробуем удалить значения массивов и только потом обнулять их" << endl;
  91. int size = _msize(book) / sizeof(book);
  92. Lib** stack = new Lib * [size];
  93. for (int i = 0; i < size; i++) {
  94. stack[i] = new Lib{ book[i]->autor,book[i]->name,book[i]->pages };
  95. }
  96. Lib*** root = &book;
  97. Lib** adrind = &book[0];
  98. const char** adr1 = &(book[0]->autor);
  99. const char** adr2 = &(book[0]->name);
  100. int* adr3 = &(book[0]->pages);
  101. cout << "В функции создана копия исходного массива указателей размером " << _msize(stack) / sizeof(stack[0]) << " элемент(ов)" << endl;
  102. cout << "Теперь функция будет удалять исходный массив и подменять указатель. Будем смотреть, что происходит в памяти на каждом шаге." << endl;
  103. for (int i = 0; i < size; i++) {
  104. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  105. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  106. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение " << *adr1 << endl;
  107. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение " << *adr2 << endl;
  108. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  109. cout << endl << "Теперь обнуляем исходный массив[i]->autor" << endl;
  110. book[i]->autor=nullptr;
  111. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  112. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  113. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  114. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение " << *adr2 << endl;
  115. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  116. cout << "исходный массив[i]->name=nullptr;" << endl;
  117. book[i]->name=nullptr;
  118. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  119. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  120. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  121. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0x00000000 и не доступно для чтения" << endl;
  122. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  123. cout << "delete[]исходный массив[i]" << endl;
  124. delete[]book[i];
  125. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  126. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  127. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  128. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  129. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  130. }
  131. delete[]book;
  132. cout << "delete[]исходный массив" << endl;
  133. cout << "Указатель на новый двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  134. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  135. cout << "Указатель \"autor\" лежит в ячейке " << adr1 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  136. cout << "Указатель \"name\" лежит в ячейке " << adr2 << " и имеет значение 0xdddddddd и не доступно для чтения" << endl;
  137. cout << "Переменная \"pages\" лежит в ячейке " << adr3 << " и имеет значение " << *adr3 << endl;
  138. cout << "Таким образом освобождена вся динамическая память, занятая указателем book. Сам указатель находится в стеке и его удалять смысла нет."<<endl;
  139. book = new Lib * [size + 1];
  140. for (int i = 0; i < size; i++) {
  141. book[i] = stack[i];
  142. }
  143. /*char* n = new char[10];
  144. cin >> n;
  145. cout << n;*/
  146. book[size] = new Lib{ autor,name,pages };
  147. }
  148.  
  149.  
  150.  
  151. int main()
  152. {
  153. setlocale(LC_ALL, "RUS");
  154. int* singlep = new int[3]{};
  155. cout << "Создаём указатель на одномерный динамический массив MASS из 3-х элементов ";
  156. cout << "по адресу в стеке "<<&singlep<<endl;
  157. for (int i = 0; i < 3; i++) {
  158. cout << "Введите значение "<<i+1<<" для этого массива: ";
  159. cin >> singlep[i];
  160. }
  161. cout << "MASS = " << singlep<<endl;
  162. for (int i = 0; i < 3; i++) {
  163. cout << "У ячейки из кучи "<<&singlep[i]<<" значение "<< singlep[i] << " "<<endl;
  164. }
  165. int* adr1 = &singlep[0];
  166. int* adr2 = &singlep[1];
  167. int* adr3 = &singlep[2];
  168. cout << "Записываем в значение указателя на MASS в стеке nullpointer - \"MASS = nullptr\""<<endl;
  169. singlep = nullptr;
  170. cout << "Теперь указатель на этот массив по адресу в стеке " << &singlep <<" содержит значение "<< singlep <<"."<< endl;
  171.  
  172. for (int i = 0; i < 3; i++) {
  173. cout << "Ячейка MASS["<<i<<"] "<< &singlep[i] << " "<<endl;
  174. }
  175. cout << "Попытка получить значения по этим адресам вызовет исключение из-за нарушений прав доступа для чтения." << endl;
  176.  
  177. cout << "У ячейки из кучи " << adr1 << " значение " << *adr1 << " " << endl;
  178. cout << "У ячейки из кучи " << adr2 << " значение " << *adr2 << " " << endl;
  179. cout << "У ячейки из кучи " << adr3 << " значение " << *adr3 << " " << endl;
  180. cout << "Теперь удаляем MASS оператором delete[] - \"delete[] MASS\"" << endl;
  181. delete[]singlep;
  182. cout << "Теперь указатель на этот массив по адресу в стеке " << &singlep << " содержит значение " << singlep << "." << endl;
  183.  
  184. for (int i = 0; i < 3; i++) {
  185. cout << "Ячейка MASS[" << i << "] " << &singlep[i] << " " << endl;
  186. }
  187. cout << "У ячейки из кучи " << adr1 << " значение " << *adr1 << " " << endl;
  188. cout << "У ячейки из кучи " << adr2 << " значение " << *adr2 << " " << endl;
  189. cout << "У ячейки из кучи " << adr3 << " значение " << *adr3 << " " << endl;
  190. cout << "Таким образом мы получаем утечку памяти по элементам исходного массива" << endl;
  191. cout << "Теперь рассмотрим другой вариант, где мы сначала удалим массив, а потом обнулим его..."<<endl;
  192. system("pause");
  193. system("cls");
  194. singlep = new int[3]{};
  195. cout << "Создаём указатель на одномерный динамический массив MASS из 3-х элементов ";
  196. cout << "по адресу в стеке " << &singlep << endl;
  197. for (int i = 0; i < 3; i++) {
  198. cout << "Введите значение " << i + 1 << " для этого массива: ";
  199. cin >> singlep[i];
  200. }
  201. cout << "MASS = " << singlep << endl;
  202. for (int i = 0; i < 3; i++) {
  203. cout << "У ячейки из кучи " << &singlep[i] << " значение " << singlep[i] << " " << endl;
  204. }
  205. adr1 = &singlep[0];
  206. adr2 = &singlep[1];
  207. adr3 = &singlep[2];
  208. cout << "Теперь удаляем MASS оператором delete[] - \"delete[] MASS\"" << endl;
  209. delete[]singlep;
  210.  
  211. cout << "Теперь указатель на этот массив по адресу в стеке " << &singlep << " содержит значение " << singlep << "." << endl;
  212. cout << "Цитата из\"Tim Burrell of the TwC Security Science team presents the fifth blog installment describing /sdl: functionality in Visual Studio 11.\":" << endl;
  213. cout << " We have chosen 0x8123 as a sanitization value – from an operating system perspective this is in the same memory page as the zero address (NULL), but an access violation at 0x8123 will better stand out to the developer as needing more detailed attention \"" << endl;
  214. for (int i = 0; i < 3; i++) {
  215. cout << "Ячейка MASS[" << i << "] " << &singlep[i] << " " << endl;
  216. }
  217. cout << "Попытка получить значения по этим адресам вызовет исключение из-за нарушений прав доступа для чтения." << endl;
  218. cout << "У ячейки из кучи " << adr1 << " значение " << *adr1 << " " << endl;
  219. cout << "У ячейки из кучи " << adr2 << " значение " << *adr2 << " " << endl;
  220. cout << "У ячейки из кучи " << adr3 << " значение " << *adr3 << " " << endl;
  221.  
  222.  
  223. cout << "Записываем в значение указателя на MASS в стеке nullpointer - \"MASS = nullptr\"" << endl;
  224. singlep = nullptr;
  225. cout << "Теперь указатель на этот массив по адресу в стеке " << &singlep << " содержит значение " << singlep << "." << endl;
  226.  
  227. for (int i = 0; i < 3; i++) {
  228. cout << "Ячейка MASS[" << i << "] " << &singlep[i] << " " << endl;
  229. }
  230. cout << "У ячейки из кучи " << adr1 << " значение " << *adr1 << " " << endl;
  231. cout << "У ячейки из кучи " << adr2 << " значение " << *adr2 << " " << endl;
  232. cout << "У ячейки из кучи " << adr3 << " значение " << *adr3 << " " << endl;
  233. cout << "Таким образом оператор delete[] освобождает память для новых значений и изменяет значение указателя на так называемое \"sanitazion value\", что делает его обнуление практически бессмысленным" << endl;;
  234. system("pause");
  235. system("cls");
  236. cout << "Теперь рассмотрим варианты сочетания delete[] и nullpointer на двумерных динамических массивах" << endl;
  237. system("pause");
  238. system("cls");
  239.  
  240.  
  241. int** doublep = new int* [3];
  242. cout << "Создаём указатель на двумерный динамический массив MASS из 3-х одномерных массивов по 3 элемента в каждом"<<endl;
  243. cout << "по адресу в стеке " << &doublep <<" со значением "<< doublep << endl;
  244. cout << "MASS[0] = new int[3]{ 1,2,3 };" << endl << "MASS[1] = new int[3]{ 4,5,6 };" << endl << "MASS[2] = new int[3]{ 7,8,9 }; " << endl;
  245. doublep[0] = new int[3]{1,2,3};
  246. doublep[1] = new int[3]{4,5,6};
  247. doublep[2] = new int[3]{7,8,9};
  248. cout << "Адрес MASS[0] " << &doublep[0] << " и значение по этому адресу " << doublep[0] << endl;
  249. cout << "Адрес MASS[1] " << &doublep[1] << " и значение по этому адресу " << doublep[1] << endl;
  250. cout << "Адрес MASS[2] " << &doublep[2] << " и значение по этому адресу " << doublep[2] << endl;
  251. int** a = &doublep[0];
  252. int** b = &doublep[1];
  253. int** c = &doublep[2];
  254. int* adrs1i1 = &doublep[0][0]; cout << "Ячейка " << adrs1i1 << " содержит значение " << doublep[0][0] << endl;
  255. int* adrs1i2 = &doublep[0][1]; cout << "Ячейка " << adrs1i2 << " содержит значение " << doublep[0][1] << endl;
  256. int* adrs1i3 = &doublep[0][2]; cout << "Ячейка " << adrs1i3 << " содержит значение " << doublep[0][2] << endl;
  257. int* adrs2i1 = &doublep[1][0]; cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  258. int* adrs2i2 = &doublep[1][1]; cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  259. int* adrs2i3 = &doublep[1][2]; cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  260. int* adrs3i1 = &doublep[2][0]; cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  261. int* adrs3i2 = &doublep[2][1]; cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  262. int* adrs3i3 = &doublep[2][2]; cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  263. cout << "Видно, что MASS - это указатель на MASS[0], а MASS[i] - это указатели на одномерные массивы из элементов MASS[i][j]" << endl;
  264. cout << "Посмотрим, что произойдёт если удалить корневой указатель MASS" << endl;
  265. delete[]doublep;
  266. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  267. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  268. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  269. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  270. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  271. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  272. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  273. cout << "Ячейка " << adrs2i1 << " содержит значение " << *adrs2i1 << endl;
  274. cout << "Ячейка " << adrs2i2 << " содержит значение " << *adrs2i2 << endl;
  275. cout << "Ячейка " << adrs2i3 << " содержит значение " << *adrs2i3 << endl;
  276. cout << "Ячейка " << adrs3i1 << " содержит значение " << *adrs3i1 << endl;
  277. cout << "Ячейка " << adrs3i2 << " содержит значение " << *adrs3i2 << endl;
  278. cout << "Ячейка " << adrs3i3 << " содержит значение " << *adrs3i3 << endl;
  279. cout << "В результате, так же как и в варианте с одномерным массивом оператор delete[] удалил значения в массиве и обнулил указатель (присвоил \"sanitazion value\"), при этом мы получили утечку памяти, потому что потеряли доступ по указателям к занятым целочисленными значениями ячейкам памяти" << endl;
  280. cout << "Теперь вернём всё в исходное состояние и вместо delete[] используем nullptr." << endl;
  281. system("pause");
  282. system("cls");
  283.  
  284. doublep = new int* [3];
  285. cout << "Создаём указатель на двумерный динамический массив MASS из 3-х одномерных массивов по 3 элемента в каждом" << endl;
  286. cout << "по адресу в стеке " << &doublep << " со значением " << doublep << endl;
  287. cout << "MASS[0] = new int[3]{ 1,2,3 };" << endl << "MASS[1] = new int[3]{ 4,5,6 };" << endl << "MASS[2] = new int[3]{ 7,8,9 }; " << endl;
  288. doublep[0] = new int[3]{ 1,2,3 };
  289. doublep[1] = new int[3]{ 4,5,6 };
  290. doublep[2] = new int[3]{ 7,8,9 };
  291. cout << "Адрес MASS[0] " << &doublep[0] << " и значение по этому адресу " << doublep[0] << endl;
  292. cout << "Адрес MASS[1] " << &doublep[1] << " и значение по этому адресу " << doublep[1] << endl;
  293. cout << "Адрес MASS[2] " << &doublep[2] << " и значение по этому адресу " << doublep[2] << endl;
  294. a = &doublep[0];
  295. b = &doublep[1];
  296. c = &doublep[2];
  297. adrs1i1 = &doublep[0][0]; cout << "Ячейка " << adrs1i1 << " содержит значение " << doublep[0][0] << endl;
  298. adrs1i2 = &doublep[0][1]; cout << "Ячейка " << adrs1i2 << " содержит значение " << doublep[0][1] << endl;
  299. adrs1i3 = &doublep[0][2]; cout << "Ячейка " << adrs1i3 << " содержит значение " << doublep[0][2] << endl;
  300. adrs2i1 = &doublep[1][0]; cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  301. adrs2i2 = &doublep[1][1]; cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  302. adrs2i3 = &doublep[1][2]; cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  303. adrs3i1 = &doublep[2][0]; cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  304. adrs3i2 = &doublep[2][1]; cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  305. adrs3i3 = &doublep[2][2]; cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  306. cout << "Посмотрим, что произойдёт если MASS присвоить значение \"nullptr\"" << endl;
  307. doublep = nullptr;
  308. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  309. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  310. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  311. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  312. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  313. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  314. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  315. cout << "Ячейка " << adrs2i1 << " содержит значение " << *adrs2i1 << endl;
  316. cout << "Ячейка " << adrs2i2 << " содержит значение " << *adrs2i2 << endl;
  317. cout << "Ячейка " << adrs2i3 << " содержит значение " << *adrs2i3 << endl;
  318. cout << "Ячейка " << adrs3i1 << " содержит значение " << *adrs3i1 << endl;
  319. cout << "Ячейка " << adrs3i2 << " содержит значение " << *adrs3i2 << endl;
  320. cout << "Ячейка " << adrs3i3 << " содержит значение " << *adrs3i3 << endl;
  321. cout << "Теперь проверим теорию, что перед удалением нужно использовать nullptr. Выполним команду delete[]MASS и посмотрим что останется в памяти" << endl;
  322. delete[]doublep;
  323. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  324. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  325. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  326. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  327. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  328. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  329. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  330. cout << "Ячейка " << adrs2i1 << " содержит значение " << *adrs2i1 << endl;
  331. cout << "Ячейка " << adrs2i2 << " содержит значение " << *adrs2i2 << endl;
  332. cout << "Ячейка " << adrs2i3 << " содержит значение " << *adrs2i3 << endl;
  333. cout << "Ячейка " << adrs3i1 << " содержит значение " << *adrs3i1 << endl;
  334. cout << "Ячейка " << adrs3i2 << " содержит значение " << *adrs3i2 << endl;
  335. cout << "Ячейка " << adrs3i3 << " содержит значение " << *adrs3i3 << endl;
  336. cout << "В результате проведённого эксперимента делаем вывод, что delete[] удаляет значения и обнуляет указатель к которому он был применён, а nullptr просто присваивает значение NULL указателю" << endl;
  337. cout << "Вернём всё к исходным значениям и проверим что произойдёт, если удалить вложенный массив MASS[0]" << endl;
  338. system("pause");
  339. system("cls");
  340. doublep = new int* [3];
  341. cout << "Создаём указатель на двумерный динамический массив MASS из 3-х одномерных массивов по 3 элемента в каждом" << endl;
  342. cout << "по адресу в стеке " << &doublep << " со значением " << doublep << endl;
  343. cout << "MASS[0] = new int[3]{ 1,2,3 };" << endl << "MASS[1] = new int[3]{ 4,5,6 };" << endl << "MASS[2] = new int[3]{ 7,8,9 }; " << endl;
  344. doublep[0] = new int[3]{ 1,2,3 };
  345. doublep[1] = new int[3]{ 4,5,6 };
  346. doublep[2] = new int[3]{ 7,8,9 };
  347. cout << "Адрес MASS[0] " << &doublep[0] << " и значение по этому адресу " << doublep[0] << endl;
  348. cout << "Адрес MASS[1] " << &doublep[1] << " и значение по этому адресу " << doublep[1] << endl;
  349. cout << "Адрес MASS[2] " << &doublep[2] << " и значение по этому адресу " << doublep[2] << endl;
  350. a = &doublep[0];
  351. b = &doublep[1];
  352. c = &doublep[2];
  353. adrs1i1 = &doublep[0][0]; cout << "Ячейка " << adrs1i1 << " содержит значение " << doublep[0][0] << endl;
  354. adrs1i2 = &doublep[0][1]; cout << "Ячейка " << adrs1i2 << " содержит значение " << doublep[0][1] << endl;
  355. adrs1i3 = &doublep[0][2]; cout << "Ячейка " << adrs1i3 << " содержит значение " << doublep[0][2] << endl;
  356. adrs2i1 = &doublep[1][0]; cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  357. adrs2i2 = &doublep[1][1]; cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  358. adrs2i3 = &doublep[1][2]; cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  359. adrs3i1 = &doublep[2][0]; cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  360. adrs3i2 = &doublep[2][1]; cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  361. adrs3i3 = &doublep[2][2]; cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  362.  
  363. cout << "Посмотрим что произойдёт если мы удалим MASS[0]" << endl;
  364. delete[]doublep[0];
  365. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  366. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  367. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  368. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  369. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  370. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  371. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  372. cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  373. cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  374. cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  375. cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  376. cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  377. cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  378. cout << "Видим, что массив MASS[0] освободил память от своих элементов, но в отличие от других примеров значение указателя MASS[0] не обнулилось. В этом варианте использование nullptr к MASS[0] было бы оправдано. Если все эти манипуляции проделать, например, с MASS[1], то результат будет аналогичным" << endl;
  379. cout << "Пробуем создать новый одномерный массив по имеющемуся указателю MASS[0], но состоящий теперь из 5-и элементов" << endl;
  380. doublep[0] = new int[5]{ -1,0,1,2,3 };
  381. cout << "Адрес MASS[0] " << &doublep[0] << " и значение по этому адресу " << doublep[0] << endl;
  382. cout << "Адрес MASS[1] " << &doublep[1] << " и значение по этому адресу " << doublep[1] << endl;
  383. cout << "Адрес MASS[2] " << &doublep[2] << " и значение по этому адресу " << doublep[2] << endl;
  384. adrs1i1 = &doublep[0][0];
  385. adrs1i2 = &doublep[0][1];
  386. adrs1i3 = &doublep[0][2];
  387. int* adrs1i4 = &doublep[0][3];
  388. int* adrs1i5 = &doublep[0][4];
  389. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  390. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  391. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  392. cout << "Ячейка " << adrs1i4 << " содержит значение " << *adrs1i4 << endl;
  393. cout << "Ячейка " << adrs1i5 << " содержит значение " << *adrs1i5 << endl;
  394. cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  395. cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  396. cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  397. cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  398. cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  399. cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  400. cout << "Значение указателя MASS[0] изменилось, т.к. мы создали новый массив в куче. Также мы смогли изменить его размер, т.к. массивы MASS[i] не связаны между собой в памяти неразрывно"<<endl;
  401. cout << "Теперь проверим что произойдёт в памяти, если перед delete[] добавить nullptr"<<endl;
  402. system("pause");
  403. system("cls");
  404. doublep = new int* [3];
  405. cout << "Создаём указатель на двумерный динамический массив MASS из 3-х одномерных массивов по 3 элемента в каждом" << endl;
  406. cout << "по адресу в стеке " << &doublep << " со значением " << doublep << endl;
  407. cout << "MASS[0] = new int[3]{ 1,2,3 };" << endl << "MASS[1] = new int[3]{ 4,5,6 };" << endl << "MASS[2] = new int[3]{ 7,8,9 }; " << endl;
  408. doublep[0] = new int[3]{ 1,2,3 };
  409. doublep[1] = new int[3]{ 4,5,6 };
  410. doublep[2] = new int[3]{ 7,8,9 };
  411. cout << "Адрес MASS[0] " << &doublep[0] << " и значение по этому адресу " << doublep[0] << endl;
  412. cout << "Адрес MASS[1] " << &doublep[1] << " и значение по этому адресу " << doublep[1] << endl;
  413. cout << "Адрес MASS[2] " << &doublep[2] << " и значение по этому адресу " << doublep[2] << endl;
  414. a = &doublep[0];
  415. b = &doublep[1];
  416. c = &doublep[2];
  417. adrs1i1 = &doublep[0][0]; cout << "Ячейка " << adrs1i1 << " содержит значение " << doublep[0][0] << endl;
  418. adrs1i2 = &doublep[0][1]; cout << "Ячейка " << adrs1i2 << " содержит значение " << doublep[0][1] << endl;
  419. adrs1i3 = &doublep[0][2]; cout << "Ячейка " << adrs1i3 << " содержит значение " << doublep[0][2] << endl;
  420. adrs2i1 = &doublep[1][0]; cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  421. adrs2i2 = &doublep[1][1]; cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  422. adrs2i3 = &doublep[1][2]; cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  423. adrs3i1 = &doublep[2][0]; cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  424. adrs3i2 = &doublep[2][1]; cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  425. adrs3i3 = &doublep[2][2]; cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  426.  
  427. cout << "Посмотрим что произойдёт если мы запишем в MASS[0] значение \"nullptr\"" << endl;
  428. doublep[0]=nullptr;
  429. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  430. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  431. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  432. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  433. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  434. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  435. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  436. cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  437. cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  438. cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  439. cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  440. cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  441. cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  442. cout << "Указатель MASS[0] стал равен нулю и больше не указывает на первый вложенный массив. Теперь выполняем команду delete[]MASS[0] и проверяем результат" << endl;
  443. delete[]doublep[0];
  444. cout << "Адрес MASS в стеке " << &doublep << " со значением " << doublep << endl;
  445. cout << "Адрес MASS[0] " << a << " и значение по этому адресу " << *a << endl;
  446. cout << "Адрес MASS[1] " << b << " и значение по этому адресу " << *b << endl;
  447. cout << "Адрес MASS[2] " << c << " и значение по этому адресу " << *c << endl;
  448. cout << "Ячейка " << adrs1i1 << " содержит значение " << *adrs1i1 << endl;
  449. cout << "Ячейка " << adrs1i2 << " содержит значение " << *adrs1i2 << endl;
  450. cout << "Ячейка " << adrs1i3 << " содержит значение " << *adrs1i3 << endl;
  451. cout << "Ячейка " << adrs2i1 << " содержит значение " << doublep[1][0] << endl;
  452. cout << "Ячейка " << adrs2i2 << " содержит значение " << doublep[1][1] << endl;
  453. cout << "Ячейка " << adrs2i3 << " содержит значение " << doublep[1][2] << endl;
  454. cout << "Ячейка " << adrs3i1 << " содержит значение " << doublep[2][0] << endl;
  455. cout << "Ячейка " << adrs3i2 << " содержит значение " << doublep[2][1] << endl;
  456. cout << "Ячейка " << adrs3i3 << " содержит значение " << doublep[2][2] << endl;
  457. cout << "В памяти ничего не изменилось. Имеем утечку памяти по первому вложенному массиву из 3-х элементов" << endl;
  458. system("pause");
  459. system("cls");
  460. cout << "Теперь посмотрим как это сработает на двумерном массиве структур" << endl;
  461. system("pause");
  462. system("cls");
  463.  
  464.  
  465.  
  466. cout << "Создаём структуру \"Lib\", состоящую из:" << endl << "const char* autor = new const char[10];" << endl << "const char* name = new const char[10];" << endl << "int pages;" << endl<<endl<<"Затем создаём 1 элемент типа Lib:"<<endl;
  467. Lib** books = new Lib * [1];
  468. books[0] = new Lib{ "Tolstoy", "War and piece", 4000 };
  469. showLib(books);
  470. cout << endl<<"Разберёмся с адресацией массивов."<<endl<<"";
  471. Lib*** root = &books;
  472. Lib** adrind = &books[0];
  473. cout << "Указатель на двумерный массив структур лежит в ячейке " << root << " и указывает на ячейку " << *root << endl;
  474. cout << "Указатель на непосредственно структуру лежит в ячейке " << adrind << " и указывает на ячейку " << *adrind << endl;
  475. const char** wadr1 = &(books[0]->autor);
  476. const char** wadr2 = &(books[0]->name);
  477. int* wadr3 = &(books[0]->pages);
  478. //const char* r = &books[0]->autor[0];
  479. cout << "Структура в свою очередь тоже состоит из 2-х указателей и одного целочисленного значения" << endl;
  480. cout << "Указатель \"autor\" лежит в ячейке " << wadr1 <<" и имеет значение "<< *wadr1 << endl;
  481. cout << "Указатель \"name\" лежит в ячейке " << wadr2 << " и имеет значение " << *wadr2 << endl;
  482. cout << "Переменная \"pages\" лежит в ячейке " << wadr3 << " и имеет значение " << *wadr3 << endl;
  483. cout << "Получается, что структура в памяти расположена непрерывно, содержит в себе 2 указателя на массивы const char (судя по размеру элементов структуры), но узнать адреса этих массивов система не даёт. И вместо адреса ячейки первого элемента массива const char, выдаёт его значение ." << endl;
  484. addLib(books, "Fuygfyu", "jgyug", 600);
  485. addLib2(books, "Fuygfyu", "jgyug", 600);
  486.  
  487. showLib(books);
  488. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement