C ++ деструктор по умолчанию - PullRequest
44 голосов
/ 29 января 2011

Когда я, например, не объявляю constructor, компилятор предоставит мне default constructor, который не будет иметь аргументов и определения (тела), и, таким образом, не будет предпринимать никаких действий .

Если я теперь не объявлю destructor, компилятор предоставит мне default destructor без определения (тело), ​​и, таким образом, я думаю без действия .

Итак, если я закончу с объектом, например, не будет ли default destructor перераспределять (свободную) память, используемую объектом?Если это не так, почему мы получаем это?

И, возможно, тот же вопрос относится к default constructor.Если он ничего не делает, почему он создан для нас по умолчанию?

Спасибо.

Ответы [ 7 ]

64 голосов
/ 29 января 2011

Нельзя сказать, что сгенерированный компилятором конструктор по умолчанию не предпринимает никаких действий. Он эквивалентен определяемому пользователем конструктору с пустым телом и пустым списком инициализатора, но это не значит, что он не предпринимает никаких действий. Вот что он делает:

  1. Он вызывает конструктор по умолчанию для базового класса.
  2. Инициализирует указатель vtable, если класс полиморфный.
  3. Вызывает конструкторы по умолчанию всех членов, которые их имеют. Если есть член с некоторыми конструкторами, но без конструктора по умолчанию, то это ошибка времени компиляции.

И только если класс не является полиморфным, не имеет базового класса и не имеет членов, требующих конструирования, конструктор по умолчанию, сгенерированный компилятором, ничего не делает. Но даже тогда конструктор по умолчанию иногда необходим по причинам, объясненным в других ответах.

То же самое относится к деструктору - он вызывает деструктор базового класса и деструкторы всех членов, у которых они есть, поэтому в общем случае неверно, что деструктор, сгенерированный компилятором, ничего не делает.

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

5 голосов
/ 29 января 2011

Потому что, если у вас нет (общедоступных) конструкторов или деструкторов, тогда объект класса не может быть создан. Рассмотрим:

class A
{
private:
    A() {}
    ~A() {}
};

A a;  // Oh dear!  Compilation error

Если вы явно не объявляете какие-либо конструкторы или деструкторы, компилятор должен предоставить их, чтобы разрешить создание объектов.

4 голосов
/ 29 января 2011

Конструктор и деструкторы по умолчанию - это просто товар, если вам не нужно делать что-то особенное с вашим классом, вам не нужно писать пустую версию вручную.Это распространено в других языках OO, например, в Java вам не нужно предоставлять конструктор, если достаточно нулевой инициализации членов.В то же время это требование обратной совместимости с C. Если у вас есть struct в C, у него не будет конструктора или деструктора (у C нет таких понятий), чтобы иметь возможность обрабатывать этот код в C ++, которыйдолжен быть действительный код.

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

На этом уровне это похоже на термин overrider , применяемый к методу в базовом классе.В базовом классе ничего не переопределяет , переопределять нечего!И все же язык явно заявляет, что виртуальный не чистый метод, объявленный в базе, является переопределением.Это позволяет спецификации просто сказать, что final overrider будет вызываться, когда метод вызывается через указатель или ссылку, без необходимости добавления extre * или реализации базового метода, если переопределения для этого конкретного метода не существуетв этой конкретной иерархии.

4 голосов
/ 29 января 2011

Деструктор по умолчанию не будет ничего делать (как конструктор по умолчанию).

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

Обратите внимание, что обычно вы должны следовать правилу из трех : если вашей программе нужно что-то делать в ее деструкторе (например, освобождение ресурсов), вы также должны предоставить конструктор копирования и оператор присваивания; C ++ также предоставляет их версии по умолчанию (которые, опять же, ничего не сделают).

Конструктор по умолчанию / деструктор / оператор присваивания / конструктор копирования полезны, когда вы работаете с простыми классами, где вам не нужно ничего делать. Особый случай - POD: они (до C ++ 0x) даже не могут иметь явных конструкторов или деструкторов.

2 голосов
/ 24 марта 2016

При использовании умных указателей деструктор по умолчанию (см. Ответ Сергея) может иметь решающее значение для предотвращения утечек памяти.Вот пример:

#include <iostream>
#include <memory>

using namespace std;

class Foo {
public:
  Foo(int n = 0): n(n) { cout << "Foo(" << n << ")" << endl; }
  ~Foo() { cout << "~Foo(" << n << ")" << endl; }
private:
  int n;
};

// notes:
// * default destructor of Bar calls destructors of unique_ptr<Foo> foo
//  and of unique_ptr<Foo[]> foo3, which, in turn, delete the Foo objects
// * foo2's Foo object leaks
class Bar {
public:
  Bar(): foo(new Foo(1)), foo2(new Foo(2)), foo3(new Foo[2]) { }
private:
  unique_ptr<Foo> foo;
  Foo* foo2;
  unique_ptr<Foo[]> foo3;
};

int main() {
  Bar bar;
  cout << "in main()" << endl;
}

Здесь вывод, показывающий, что утечка происходит только для foo2:

Foo(1)
Foo(2)
Foo(0)
Foo(0)
in main()
~Foo(0)
~Foo(0)
~Foo(1)
1 голос
/ 29 января 2011

Короткий ответ: в C ++ каждый объект нуждается в конструкторе и деструкторе, даже если они ничего не делают. Таким образом, компилятор, создающий их для вас в фоновом режиме, удовлетворяет этому требованию.

Более длинный ответ заключается в том, что конструкторы отвечают за инициализацию членов класса. Конструктор по умолчанию выполняет инициализацию по умолчанию для всех элементов. (Это ничего не значит для типов POD, но другие классы получают свои конструкторы по умолчанию.)

0 голосов
/ 29 января 2011

Деструктор по умолчанию не может знать, какой памяти «принадлежит» ваш класс, чтобы иметь возможность освободить его.

Что касается части конструктора по умолчанию, я процитирую статью Википедии об этом ...

В C ++ конструкторы по умолчанию имеют большое значение, потому что они автоматически вызывается в определенных обстоятельства:

  • Когда значение объекта объявляется без списка аргументов, например, Мои занятия Икс;; или распределяется динамически без список аргументов, например новый MyClass; конструктор по умолчанию используется для инициализировать объект
  • Когда объявляется массив объектов, например, MyClass x [10] ;; или же распределяется динамически, например, новый MyClass [10]; конструктор по умолчанию используется для инициализации всех элементов
  • Когда конструктор производного класса явно не вызывает базу конструктор класса в его инициализаторе список, конструктор по умолчанию для Базовый класс называется
  • Когда конструктор класса не вызывает явно конструктор одно из его объектно-значимых полей в его список инициализаторов, по умолчанию Конструктор для класса поля называется
  • В стандартной библиотеке некоторые контейнеры «заполняют» значения, используя конструктор по умолчанию, когда значение явно не указано, например вектор (10); инициализирует вектор с 10 элементами, которые заполнены по умолчанию построен ценность нашего типа.

в выше обстоятельства, это ошибка, если класс не имеет значения по умолчанию конструктор. Компилятор будет неявно определить значение по умолчанию конструктор

если нет конструкторов явно определены для класса. это неявно объявленный дефолт Конструктор эквивалентен по умолчанию конструктор определяется с пустым телом. (Примечание: если некоторые конструкторы определены, но все они не по умолчанию, компилятор не будет неявно определить конструктор по умолчанию. это означает, что конструктор по умолчанию может не существует для класса.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...