#c #memory #memory-leaks
#c #память #утечки памяти
Вопрос:
Я читаю некоторые вещи и наткнулся на это:
Деструкторы вызываются, когда переменная выходит за пределы области видимости
Итак, мой вопрос в том, что происходит с переменными, у которых нет деструкторов?
В качестве примера:
class A {
public:
A () { }
};
void foo () {
A a;
}
int main (void) {
foo();
}
Итак, в данном случае a()
? Будет ли память, которая была выделена для a
, уничтожена после foo()
завершения или нет?
Чем у меня есть этот пример:
class A {
std::vector <int> aa;
public:
A () : aa(5) { }
};
void foo () {
A b;
}
int main (void) {
foo();
}
В этом случае также будет ли память, которая была выделена для b
уничтожения после foo()
завершения, или нет?
Еще одно уточнение, я знаю это:
class A {
public:
A () { }
};
эквивалентно
class A {
public:
A () { }
inline ~A() = default;
};
Но мой вопрос в том, вызывается ли это встроенное уничтожение, когда foo()
выполняется?
РЕДАКТИРОВАТЬ: Когда был inline
добавлен деструктор по умолчанию?
Комментарии:
1.
A a();
— Это не создает объект. Объявляется вызываемая функция,a()
которая не принимает параметров и возвращаетA
объект.2. @Gox Вызов
foo();
inmain()
, вероятно, был бы оптимизирован любым приличным компилятором c , поскольку эта функция не имеет никакого эффекта.3. Примечание: Деструктор не освобождает память уничтожаемого объекта. Чаще всего вызывается как часть цепочки, ведущей к освобождению памяти, но может вызываться отдельно для уничтожения объекта без освобождения памяти. Подробнее об этом см. в разделе Размещение new / delete .
Ответ №1:
Если вы не предоставляете деструктор, компилятор предоставит его для вас. Этот деструктор вызовет деструкторы любых переменных-членов и базовых классов.
Есть несколько случаев, в которых вы должны написать деструктор, чтобы избежать утечек. Один из случаев заключается в том, что вы держите пустой указатель на что-то, выделенное с помощью new
, и ваш объект является лучшим кандидатом на «владение» этим указателем. В большинстве случаев, когда вы выделяете что-то с помощью new
, вы считаете себя владельцем указателя.
Другой случай — это когда вы приобрели какой-то другой ресурс и вам нужно его освободить. Например, если вы открываете файл или сокет, вам, вероятно, потребуется написать пользовательский деструктор, чтобы закрыть его.
Однако то, что я делаю для всех таких ресурсов, заключается в том, что я создаю класс, который оборачивает ресурс и имеет деструктор, который его закрывает. Это локализует проблему, поэтому я должен помнить как можно меньше об управлении ресурсами для большей части моего кода. Это распространенная идиома в C , которая называется RAII, что означает «Получение ресурсов — это инициализация».
Вот почему вы также должны предпочесть make_unique
и make_shared
или такие вещи, как vector
, выделению памяти с помощью new
. Они предоставляют вам объекты, которые обертывают ресурс памяти, деструкторы которых автоматически освободят ресурс для вас.
Чтобы более подробно ответить на вопрос в вашем комментарии к моему ответу…
Деструктор локальной переменной вызывается, как только элемент управления покидает блок, в котором он был объявлен. Для конкретного примера:
void foo () {
A b;
{
A c;
} // Destructor for c is called here
} // Destructor for b is called here.
Комментарии:
1. @Gox — Да, для переменной в стеке деструктор вызывается, когда завершается блок, в котором он был объявлен.
2. @Gox — Я добавил более полный ответ на ваш вопрос в комментарии к моему ответу. И, пожалуйста.
Ответ №2:
Из стандарта:
Если класс не имеет деструктора, объявленного пользователем, деструктор неявно объявляется как установленный по умолчанию ([dcl.fct.def]). Неявно объявленный деструктор является
inline public
членом своего класса.
Другими словами,
class A {
public:
A () { }
};
эквивалентно
class A {
public:
A () { }
inline ~A() = default;
};
Что касается вашего вопроса
Но мой вопрос в том, вызывается ли это встроенное уничтожение, когда
foo()
выполняется?
Ответ — да. Однако это верно даже для определяемого пользователем деструктора.
Комментарии:
1. @Gox, ты пытаешься выяснить, когда вызывается деструктор?
2. @Gox, кто говорит об утечке памяти для таких объектов?
3. @Gox, я слышу твое разочарование. Я надеюсь, что вы придерживаетесь языка. Как и любой приобретенный навык, это становится проще с практикой. Желаю удачи.
4. вы пытаетесь выяснить, когда вызывается деструктор? ДА. Кто говорит об утечке памяти для таких объектов? несколько старых руководств по легкому изучению C . Кто-то порекомендовал мне прочитать эту печатную версию этого руководства.
5. @Gox, встроенные деструкторы существуют уже давно. Я использую его с 1995 года. Это, безусловно, было частью стандарта C 98.