C++: удалить структуру?
у меня есть структура, содержащая указатели:
struct foo
{
char* f;
int* d;
wchar* m;
}
у меня есть вектор общих указателей на эти структуры:
vector<shared_ptr<foo>> vec;
vec
выделяется в стеке. Когда он выйдет из области действия в конце метода, будет вызван его деструктор. (Не так ли?) Это, в свою очередь, вызовет деструктор каждого элемента в векторе. (Не так ли?) Does calling delete foo
удалить только указатели, такие как foo.f
, или это действительно освобождает память из кучи?
6 ответов
delete foo;
удалит память, выделенную структуре foo, которая включает в себя три указателя. Но память, на которую указывают сами указатели, будет удалена только в том случае, если вы реализуете деструктор, который явно удаляет их.
если вы динамически выделили foo
, например:
foo* f = new foo;
затем delete f
уничтожит динамически выделяемой foo
объект, включая указатели, которые он содержит, но не все, на что указывают указатели, если они действительно указывают на динамически выделенные объекты или массивы объектов.
если вы назначили динамически выделяемой foo
объект (т. е. результат new foo
) к shared_ptr
(предполагая tr1 или boost), то когда последний shared_ptr
ссылка на этот объект выходит за рамки delete
будет вызываться на указателе, первоначально возвращенном new foo
автоматически. Вам не нужно делать это вручную.
если ваш объект (foo
) содержит указатели на динамически выделенные объекты, которыми он владеет (поэтому необходимо освободить в конце срока службы foo
), то настоятельно рекомендуется написать деструктор, чтобы освободить эти объекты правильным образом (что будет зависеть от того, как они размещенный.)
после того, как вы написали деструктор, вам нужно рассмотреть, нужно ли писать конструктор копирования и оператор копирования. Поскольку вы используете вектор общих указателей, вы можете решить, что ваши объекты не должны копироваться. Если это так, вы можете объявить их как частные и не должны предоставлять реализацию.
вы также должны рассмотреть один или несколько конструкторов, чтобы убедиться, что ваши члены указателя инициализированы. Если члены указателя никогда инициализируется, если они не назначены в течение жизни foo
тогда они не будут ни нулевыми, ни указывать на допустимый объект, и это, вероятно, вызовет ошибку в вашем деструкторе.
в вашем вопросе, похоже, есть некоторая терминологическая путаница. Деструктор вектора вызовет деструкторы для shared_ptr
элементы, которые в свою очередь будут внутренне проанализировать delete
на их хранятся указатели (при необходимости).
вызов delete foo
, где foo
- это указатель на struct foo
, вызовет деструктор struct foo
а затем освободить память, занятую *foo
.
деструктор выше struct foo
абсолютно ничего не делает. Это тривиально. Если будет не делайте никаких попыток освободить память, на которую указывает struct foo::f
или любые другие члены. С чего бы это? Он не знает и не может знать, Следует ли освобождать эту память.
на самом деле, потому что struct foo::~foo
тривиально, компиляторы обычно даже не пытаются его вызвать.
ты не звонишь delete f
где f-объект типа foo
если f
выделен стек. Вы также не звоните delete f
на куче выделен объект типа foo
если этот адрес хранится в общий указатель. shared_ptr
objects вызовет delete
для вас, когда последняя ссылка освобождается.
поскольку ваш вектор хранит умные указатели, они также выпадут из области, когда ваш вектор выпадет из области и foo
будет вызван деструктор и связанная память освобожденный. Памяти foo
- это только размер 3 указателей. Не то, что содержат эти указатели.
если члены foo
выделяются кучи, тогда вам нужно будет delete
их отдельно. Например, возможно, в деструкторе foo, если память, на которую они указывают, не разделяется между объектами.
когда он выйдет из области действия в конце метода, будет вызван его деструктор. (Не так ли?)
право.
это, в свою очередь, вызовет деструктор каждого элемента в векторе. (Не так ли?)
право. Деструктор интеллектуального указателя.
или это действительно освобождает память из кучи?
он вызывает деструктор интеллектуального указателя, если больше нет ссылок на этот указатель, то объект, который он содержит, будет удален, и его память будет освободитесь.
когда он [vec] выходит из области действия в конце метода, его деструктор будет вызван. (Не так ли?)
Правильно
это, в свою очередь, вызовет деструктор каждого элемента в векторе. (Не так ли?)
Правильно, это удалит элементы shared_ptr в контейнере, и если они являются последними, а также элементы, которые они совместно используют.
делает вызов delete foo ...?
Вы не можете удалить foo, это структура. Вы можете удалить экземпляр foo.
Вызов delete вызывает деструктор и освобождает память для структуры foo.
удаляет ли деструктор foo только указатели, такие как foo::f, или он действительно освобождает память из кучи?
Это зависит от destructo, в этом случае у вас есть деструктор по умолчанию и так далее...
Нет, в следующем примере кода Вы можете увидеть некоторые из причин, почему деструктор по умолчанию, связанный с foo невозможно автоматически очистить все указатели.
{
char ca='a', *cb=new char;
int *i = (int*)malloc(sizeof(int));
foo a;
shared_ptr<foo> b = new foo();
a.f = &ca;
a.d = i;
b.f = cb;
}