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;
}