当跳过声明时,为什么需要微不足道的析构函数?

问题描述:

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:

   跳过自动变量的定义将会对是否该变量的析构函数应在年底运行的问题该块。因此,析构函数必须是微不足道的,即不起作用。类似地,默认的构造函数(可能用于初始化对象的构造函数)也不需要做任何事情,即不重要。没有其他要求是必要的。

我想记住的情况是:

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

+0

@Barry第一个'break;'从不执行,因为'i'的值是'2'。问题是* second *'break'是否应该破坏'st',即使它没有被初始化,也没有在'case 2'语句中使用。如果没有专门的措辞来防止它被破坏,那么破坏它可能不是正确的做法。因此禁止跳到'案件2'。 – hvd

+0

啊,是的。应该把所有这些都添加到答案中。 – Barry

+0

谢谢!在这两行之间进行阅读,本文似乎是说,如果构造函数的概念运行,析构函数应该运行。对我来说,如果对象可以在范围内使用,那么它是有效构造的,并且析构函数肯定应该运行。嗯... – Potatoswatter