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

При переходе через декларацию, зачем нужен тривиальный деструктор?

goto или switch может перескакивать через выражение-выражение, учитывая, что у него нет инициализатора, а конструкция тривиальна и что объект также тривиально разрушаемый.

Какое обоснование ограничения на деструктор?

struct trivial {
    trivial() = default;
    ~ trivial() = default;
};

struct semi_trivial {
    semi_trivial() = default;
    ~ semi_trivial() noexcept { do_something(); }
};

void foo() {
    goto good_label;  // OK
    trivial foo;
good_label:

    goto bad_label;   // Error: this goto statement
    semi_trivial bar; // cannot jump over this declaration.
bad_label:

    std::cout << "hi\n";
}
4b9b3361

Ответ 1

Текущая формулировка является результатом N2762. В статье дается следующее обоснование:

6.7 stmt.dcl:

  Прыгая по определению автоматической переменной, возникает проблема того, должен ли деструктор этой переменной запускаться в конце блока. Таким образом, деструктор должен быть тривиальным, то есть не иметь эффекта. Аналогично, конструктор по умолчанию (тот, который потенциально используется для инициализации объекта) также должен ничего не делать, т.е. Быть тривиальным. Никаких других требований не требуется.

Я думаю, что иметь в виду:

int i = 2;
switch (i) {
  case 1:
    semi_trivial st;
    do_something(st);
    break;
  case 2:
    break; // should st be destructed here?
}

И на самом деле это непростой вопрос. Вызов деструктора не будет, очевидно, правильным. Там нет хорошего способа сказать, следует ли его называть. Переменная st здесь используется только в операциях case 1, и программисты будут удивлены, если ее деструктор вызван оператором case 2 break, хотя он был полностью не использован и не сконструирован.