Область действия объекта в массиве
Предположим, у вас есть массив объектов в C++, и вы удаляете один из объектов из массива. Когда вызывается деструктор этого объекта? Поскольку в C++ нет автоматического сбора мусора, было бы странно, если бы деструктор вызывался сразу после удаления из массива. Но остается ли объект выделенным, пока массив не выйдет из области видимости? Кажется, это приведет к утечке памяти.
Редактировать:
Вместо "удалить" как насчет установки одного из элементов массива в другой объект.
Кроме того, что происходит, когда элемент удаляется из std::vector
?
4 ответа
Когда вы объявляете массив C++, он создает все объекты в стеке и остается там до тех пор, пока сам массив не будет удален:
std::string ArrayOfStrings[10]; //There are now ten strings here
Объекты не могут быть "удалены" из этого вида массива. Когда ArrayOfStrings выходит из области видимости, он автоматически удаляет все строки в массиве. Если вы редактируете объект в этом массиве, сам этот объект изменяется. Вы фактически изменили саму строку, а не какой-либо указатель или ссылку.
Если у вас есть массив указателей, то C++ создает все указатели, но вы должны сами управлять тем, на что они указывают:
std::string* ArrayOfPointersToStrings[10];
Вы можете вручную удалить строки, на которые указывают указатели в массиве, но вы должны сделать все это самостоятельно. Когда ArrayOfPointersToStrings выходит из области видимости, он НЕ удаляет ничего, на что указывают строки. Если вы редактируете указатель, не удаляя его в первую очередь, это утечка памяти, и это плохо.
Если у вас есть std::vector, C++ создает только некоторые объекты в зависимости от того, как вы его создаете:
std::vector<std::string> VectorOfStrings(10);
Это создает динамический массив строк. Можно удалить объекты из вектора, и в этом случае вектор мгновенно удаляет его и переставляет все остальное для вас. Если вы редактируете объект в этом массиве, сам этот объект изменяется. Вы фактически изменили саму строку, а не какой-либо указатель или ссылку.
Чтобы уточнить комментарии:
char *myLiteral = "APPLE";
//"APPLE" is an immutable string, myLiteral points at it.
std::string s= myLiteral;
std::string t = myLiteral;
//s and t each makes a _seperate_ _mutable_ copy of "APPLE"
s[3] = '?';
//s is now "APP?E", because we just changed the L. NO COPY WAS DONE.
std::cout << t[3];
//displays "L", because t's copy was never changed.
Вы не можете "удалить один из объектов из массива". Массивы имеют фиксированный размер. Все содержимое создается в тот момент, когда массив создается и уничтожается, когда сам массив уничтожается.
Если вы просто присваиваете новое значение элементу массива, то вы вызываете объект =
оператор, и он ведет себя не иначе, чем если бы вы имели простую автономную переменную и присвоили ей новое значение. Никакие объекты не обязательно построены или разрушены. Если есть какой-либо новый объект, это временный объект, который генерирует компилятор для правой части оператора присваивания. После завершения оператора временный объект уничтожается. Объект в массиве остается без изменений.
Когда вы удаляете элемент из vector
его деструктор вызывается, как и следовало ожидать, и более поздние элементы сдвигаются вниз, чтобы заполнить пробел.
Для стандартного контейнера, как std::vector
к тому времени, когда метод удаления завершает объект, был уничтожен.
Для массива "c-style" сам объект будет работать так же долго, как если бы его не было в массиве.
Время жизни объекта зависит от того, где объект был размещен. Если он находится в стеке, он освобождается, когда заканчивается текущая область, если он находится в куче, он не будет освобожден до delete
называется на это. Последний случай приводит к утечкам памяти, если объект никогда не освобождается.
Вы не можете удалить объекты из ванильного массива C++. Когда вы объявляете массив определенного размера, независимо от того, находится ли он в стеке или в куче, предполагая, что выделение прошло успешно, выделяется достаточно памяти для создания N объектов этого типа, и они создаются с использованием любого подходящего конструктора.
Использование оператора присваивания для копирования содержимого RHS к объекту в массиве обычно ничего не делает с объектом в RHS. Память в массиве просто перезаписывается. Новые объекты не создаются и не удаляются (если вы не делаете что-то вроде obj1 = obj2 = obj3
а это целая другая банка червей...)