Каков механизм вызова деструкторов для объектов, назначенных стеком? - PullRequest
2 голосов
/ 01 сентября 2009

Как C ++ обеспечивает вызов деструкторов для объектов, назначенных стеком? Что происходит с функцией деструктора (или указателем на нее), когда я назначаю динамическую память следующим образом:

class MyClass {
public:

  ~MyClass()
  {
    std::cout<<"Destructor called."<<std::endl;
  }  

  MyClass()
  {
    std::cout<<"Constructor called."<<std::endl;
  }

};

....................................................................

//Limit scope for example
{
  MyClass instance;
}

Конструктор и деструктор оба называются. Что здесь происходит?

Ответы [ 6 ]

7 голосов
/ 01 сентября 2009

Компилятор вставляет вызов деструктора для объекта в соответствующей позиции.

4 голосов
/ 01 сентября 2009

Вы не удивитесь, почему это

{
  int i;
}

автоматически создает и уничтожает i, не так ли? C ++ многое делает для того, чтобы вы могли создавать типы, которые ведут себя так же, как встроенные типы. И так же, как со встроенными типами, в C ++ (кроме, скажем, в Java или C #) это

{
  MyClass instance;
}

не просто определяет ссылку, которая может быть связана с null или каким-либо реальным объектом. Это создает фактический объект.

Создание объекта происходит в два этапа: во-первых (при входе в область действия) предоставляется необработанная память. Затем (когда определение объекта встречается) вызывается конструктор. Для встроенных типов конструктор не вызывается. Если вы не инициализируете встроенную переменную, она имеет случайное значение. (На самом деле это тот битовый шаблон, который был в памяти, предоставленной на шаге № 1). Удаление объекта также происходит в два этапа: сначала вызывается деструктор (опять же, не для встроенных модулей), затем память возвращается к система времени выполнения.

(Обратите внимание, что предоставление и удаление памяти для переменных стека обычно обходится дешевле, чем ввод / уменьшение регистра.)

3 голосов
/ 01 сентября 2009

Да, и конструктор и деструктор называются. И еще важнее:

{
 MyClass instance;
 throw "exception";
}

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

3 голосов
/ 01 сентября 2009

Конструктор вызывается, как только создается переменная. Что касается деструктора, то компилятор выдает код в конце области видимости для вызова деструктора. Чтобы почувствовать это, попробуйте использовать конструкцию 'goto' или switch / case, чтобы преждевременно выйти из области видимости и посмотреть, как компилятор жалуется.

1 голос
/ 01 сентября 2009

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

0 голосов
/ 05 ноября 2009

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

int main() {
    MyClass obj;
    cout<<"testing....1"<<endl;
    cout<<"testing....2"<<endl;
    return 0;
}

и:

Constructor called.
testing....1
testing....2
Destructor called.
...