Я до сих пор не убежден в том, что «деструктор» вызывается без «объекта» - PullRequest
0 голосов
/ 13 ноября 2011

Дело 1

Это было основано на другом моем вопросе , опубликованном вчера, который я принял, хотя и неохотно, который можно обобщить с помощью следующего кода:

{
    ...
    goto Label;
    A a;
    ...
    Label:DoSomething();
}

где A - любой класс с определенным constructor и значением по умолчанию destructor. DoSomething() не использует a. Из моего понимания (я все еще борюсь с базовыми конструкциями C ++) деструктор A не будет вызван в этой ситуации, поскольку объект a даже не был создан.

Обратите внимание, что компилятор VS2008 выдает предупреждение (C4533 : initialization of 'a' is skipped by 'goto Label'), а не ошибку, если вы не попытаетесь определить destructor для A, когда компилятор загадочным образом превращает предупреждение в ошибку (C2362 : initialization of 'a' is skipped by 'goto Label') как бы блокировать кого-то, чтобы исследовать проблему, которая, кстати, напомнила мне квантовое явление в природе.

Дело 2

Это нормальное явление constructor, создающего исключение, в этом случае destructor не вызывается, как обсуждено здесь и здесь .

Поэтому

В Case1 constructor не вызывается, но destructor вызывается для уничтожения чего-то, что не было создано, что мне кажется странным. В Case2 вызывается конструктор, выдает исключение и destructor не вызывается, что мне кажется разумным.

Я считаю, что эти два примера заслуживают дальнейшего пояснения.

Редактировать

В Case2 компилятор, вероятно, использует флаги, чтобы избежать уничтожения объектов, которые не были созданы из-за броска. Почему те же флаги нельзя использовать в Case1 для идентификации объектов, которые не были построены из-за goto?

Ответы [ 2 ]

4 голосов
/ 13 ноября 2011

В C ++ переходы через инициализацию переменных (вызовы конструктора) запрещены именно по этой причине: goto пропускает вызов конструктора. После goto и вызова DoSomething переменная a выйдет из области видимости, поэтому деструктор будет вызван на a, который не был создан, потому что goto пропустил вызов конструктора.

VS2008 здесь снисходительно и допускает нарушение стандарта, когда автоматически сгенерированный деструктор, вероятно, на POD, не действует.

3 голосов
/ 13 ноября 2011

На самом деле случай 1 является недействительным C ++. Компилятор должен выдать диагностику для этого и может вообще его не компилировать. Если компилятор все равно его скомпилирует, компилятору решать, что с ним делать. Было бы разумно не разрушать объект в этом случае, однако это требует дополнительных механизмов, а это означает ненужные накладные расходы для правильных программ (программе необходимо проверить внутренний флаг, был ли объект создан). Я не думаю, что во время компиляции всегда можно решить, нужна ли эта проверка, потому что это, вероятно, будет эквивалентно проблеме остановки.

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