考虑一个简单的例子(注意析构函数是私有的):
class Resource {
private:
~Resource() = default;
};
int main(int argc, char** argv) {
// Object on the stack
Resource r1; // line L1
// Object on the heap
Resource* r2 = new Resource();
delete r2; // line L2
return 0;
}
在MSVC 2017中编译此片段,正如我所期望的那样,在L1和L2行上出现两个C2248错误,表示无法访问~Resource
析构函数。
现在,如果我们向Resource
类添加另一个原始字段,请说int
:
class Resource {
private:
int x = 0;
~Resource() = default;
};
编译结果突然改变:现在L1线不再给出错误,只有L2。
如果不是原始类型,我们使用更复杂类型的类成员,如vector
,则第二次编译错误将再次出现。
最后,如果不是默认析构函数,我们会明确地提供一个空体:
class Resource {
private:
~Resource() {};
};
然后在所有上述情况中都会出现2个错误。
使用GCC和Clang编译的相同片段总是会为两个析构函数产生2个错误。
所以问题是: 尽管它可能只是一个编译器错误,但我怀疑这种行为可能与基于字段和用户提供的析构函数是否为聚合的类有关。 这种行为的实际原因是什么?或者更确切地说:编译器是否可以忽略析构函数的私有性?
修改:这是godbolt.org上此设置的链接。通过(联合国)评论int x = 0;
行可以看到此行为。