Программирование. Принципы и практика использования C++ Исправленное издание, стр. 265
// ... if (x) p = q; // устанавливаем указатель p на другой объект // ... delete[] p; // освобождаем память}Мы включили в программу инструкцию
if (x)pdeletevoid suspicious(int s, int x){ int* p = new int[s]; // занимаем память // ... if (x) return; // ... delete[] p; // освобождаем память}Возможно, программа никогда не выполнит оператор
deletevoid suspicious(int s, int x){ int* p = new int[s]; // занимаем память vector<int> v; // ... if (x) p[x] = v.at(x); // ... delete[] p; // освобождаем память}
void suspicious(int s, int x) // плохой код{ int* p = new int[s]; // занимаем память vector<int> v; // ... try { if (x) p[x] = v.at(x); // ... } catch (...) { // перехватываем все исключения delete[] p; // освобождаем память throw; // генерируем исключение повторно } // ... delete[] p; // освобождаем память}Этот код решает проблему за счет дополнительных инструкций и дублирования кода, освобождающего ресурсы (в данном случае инструкции
delete[] p;void suspicious(vector<int>& v, int s){ int* p = new int[s]; vector<int>v1; // ... int* q = new int[s]; vector<double> v2; // ... delete[] p; delete[] q;}Обратите внимание на то, что, если оператор
newbad_alloctry ... catctryПОПРОБУЙТЕ
Добавьте блоки
try19.5.2. Получение ресурсов — это инициализация
К счастью, нам не обязательно копировать инструкции
try...catchvoid f(vector<int>& v, int s){ vector<int> p(s); vector<int> q(s); // ...}
iostreamРассмотрим предыдущий пример. Как только мы выйдем из функции
f()pqpqreturnЭто универсальное правило: когда поток управления покидает область видимости, вызываются деструкторы для каждого полностью созданного объекта и активизированного подобъекта. Объект считается полностью созданным, если его конструктор закончил свою работу. Исследование всех следствий, вытекающих из этих двух утверждений, может вызвать головную боль. Будем считать просто, что конструкторы и деструкторы вызываются, когда надо и где надо.