Подтвердить что ты не робот

Деструктор по умолчанию для С++

Если я не объявляю constructor, например, компилятор предоставит мне default constructor, у которого не будет аргументов и нет определения (body), и, таким образом, он примет no action.

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

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

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

Спасибо.

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

A a;  // Oh dear!  Compilation error

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

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

Ответ 7

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

#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 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)