Intereting Posts
Шаблон переменной в classе QT Subdir – Неопределенная ссылка на главную – Ошибка Progressbar Диапазон и положение, как обрабатывать большие числа в C ++? Библиотеки BOOST в режиме многопоточности Оптимальное и портативное преобразование endian в c / c ++ Стандартная библиотека C ++ – std :: setenv vs setenv Как я могу взять один элемент из библиотеки boost (например, shared_pointer)? Как определить Максимальное количество событий в многомониторной системе Как использовать std :: stoul и std :: stoull в Android? Вызов указателя функции элемента C ++ из структуры Почему C ++ не печатает адрес памяти символа, но будет печатать int или bool? Как scoped_lock избегает выдавать предупреждение «неиспользуемая переменная»? Существует ли ограничение на работу с матрицей в R с Rcpp? Дифференцирование деления от регулярного выражения при использовании кода gokk lexing Ошибка: C2228: слева от ” должен быть class / структура / объединение

C ++ освобождает всю память, используемую struct

Быстрый вопрос; Я уже много раз встречался и нашел ответы, но я немного параноик, поэтому хочу быть уверенным.

Рассмотрим эту ситуацию:

struct CoordLocation { float X; float Y; float Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

Будет ли вызов delete также очистить память, используемую полями X, Y, Z? В некоторых ответах, которые я нашел, упоминалось, что я просто удалю POINTER, а не объект, на который ссылается этот объект. Что, если…

 struct CoordLocation { float *X; float *Y; float *Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

И что, если я вручную освобожу память для каждого объекта внутри конструктора / деструктора структуры?

 struct CoordLocation { CoordLocation() { *X = new float; *Y = new float; *Z = new float; } ~CoordLocation() { delete X; delete Y; delete Z; } float *X; float *Y; float *Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

Я заметил, что для простой ситуации, такой как:

  float *a = new float; *a = 5.0f; printf("%f", *a); delete a; printf("%f", &a); 

printf будет печатать 5.0, поэтому переменная, на которую указывает а, не точно уничтожена.

Поэтому мой вопрос: как я могу надежно освобождать (как в случае утечек памяти) ВСЕ память, используемая структурой в этом случае?

 struct CoordLocation { float X; float Y; float Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

Спасибо!

Вам нужно только delete память, которую вы выделяете, с new .

printf будет печатать 5.0, поэтому переменная, на которую указывает а, не точно уничтожена.

Вы фактически сталкиваетесь с неопределенным поведением. Хотя значение все еще существует, память была выпущена и может быть повторно использована.

Итак, следующее:

 struct CoordLocation { float X; float Y; float Z; }; 

не может создать утечку памяти, если вы опустите деструктор.

Ваш следующий fragment:

 struct CoordLocation { float *X; float *Y; float *Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

может потенциально создать утечку памяти, но не так, как есть. Следующее:

 int main() { CoordLocation *coord = new CoordLocation(); coord->X = new float(); delete coord; return 0; } 

Ваш третий пример

 struct CoordLocation { CoordLocation() { *X = new float; *Y = new float; *Z = new float; } ~CoordLocation() { delete X; delete Y; delete Z; } float *X; float *Y; float *Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

не создаст утечку памяти, потому что вы освободите всю память, которую вы выделите. Если вы должны были опустить деструктор или забыть вызвать команду delete coord; , у вас будет утечка памяти.

Хорошее эмпирическое правило: вызовите delete для каждого new и delete[] для каждого new[] и вы в безопасности.

В этом примере:

 struct CoordLocation { float X; float Y; float Z; }; int main() { CoordLocation *coord = new CoordLocation(); delete coord; return 0; } 

Память освобождается . В этом коде нет утечек. На примере, который вы указали, где ваша структура содержит указатели, пока вы освобождаете их в деструкторе (как и в вашем примере), утечек не будет.

В этом fragmentе:

 float *a = new float; *a = 5.0f; printf("%f", *a); delete a; printf("%f", &a); 

Значение a остается неизменным после удаления, так как delete (ing) указатель будет отмечать только адрес памяти как «освобожденный», он не будет изменять его содержимое. Доступ к свободным указателям – это неопределенное поведение.

Сам указатель выделяется с автоматическим временем хранения, там нет ничего свободного. Структура – это три поля, которые освобождаются при вызове delete . Вы вызываете delete только на то, что было возвращено new .

Когда вы выделяете что-то, вы выделяете достаточно памяти для его хранения, а это значит, что достаточно памяти для хранения всех своих полей (и некоторая служебная память, специфичная для реализации, но вы не беспокоитесь об этом). Когда вы удаляете его, вы освобождаете тот же объем памяти, который вы выделили.

Одно дело отметить, например, такой случай (в C ++ вы не создали бы такой тип, но этот пример имеет значение):

 struct Foo { char *str; }; Foo *f = new Foo(); f->str = new char[10]; delete f; 

В этом случае у вас есть утечка. Вы удаляете f , который состоит из достаточной памяти для хранения одного char* , но то, что указывает этот char* , было также динамически распределено. Итак, вам нужно также освободить его:

 delete f->str; delete f; 

Опять же, в C ++ вы, вероятно, не будете создавать такой тип, вместо этого предпочитаете такие типы, как std::string и такие принципы, как RAII, но этот пример имеет значение.