跳过声明时,为什么需要平凡的析构函数?

When jumping over a declaration, why is trivial destructor required?

gotoswitch 可以跳过声明语句,因为它没有初始化器并且构造是微不足道的——而且对象也是微不足道的 可破坏.

对析构函数进行约束的理由是什么?

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";
}

当前的措辞是 N2762 的结果。该论文给出了以下理由:

6.7 stmt.dcl:

    Jumping over the definition of an automatic variable will pose the problem of whether the destructor for that variable should be run at the end of the block. Thus, the destructor needs to be trivial, i.e. have no effect. Similarly, the default constructor (the one potentially used to initialize the object) is also required to not do anything, i.e. be trivial. No other requirements are necessary.

我认为要记住的情况是:

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 2break 语句调用,程序员会感到惊讶,即使它完全在那里未使用且未构建。