【发布时间】:2020-12-03 11:05:31
【问题描述】:
下面的sn-p代码格式正确吗?
struct A { ~A() = delete; };
A *pa{new A{}};
class B { ~B() = default; };
B *pb{new B{}};
乍一看,A 的已删除 dtor 和 B 的私有显式默认 dtor 似乎从未使用过(如果您愿意的话,这是故意的内存泄漏),这可以说是结构良好。
Clang 接受适用于各种编译器和 C++ 版本(C++11 到 C++2a)的程序。
另一方面,GCC 拒绝各种编译器和 C++ 版本的程序。
struct A { ~A() = delete; }; A *pa{new A{}}; // GCC error: use of deleted function 'A::~A()' class B { ~B() = default; }; B *pb{new B{}}; // GCC error: 'B::~B()' is private within this context
(如果格式正确;在我提交错误报告之前:是否有针对这种极端情况的开放 GCC 错误报告?我自己搜索了 GCC:s bugzilla 无济于事。)
特别是 GCC 接受私有 用户提供的析构函数的情况:
class C { ~C(); };
C *pc{new C{}}; // OK
class D { ~D() {} };
D *pd{new D{}}; // OK
这可能暗示某些 GCC 为聚合类做一些特殊的事情,因为 A 和 B 是聚合,而 C 和 D 不是。但是 GCC 与此行为不一致,如下例所示
struct E {
~E() = delete;
private:
int x;
};
E *pe{new E{}};
其中E 不是聚合(私有数据成员)同样被拒绝,就像上面聚合类A 和B 一样,而下面F 和G 的示例(聚合直到C++20 和非聚合)
struct F {
F() = default;
~F() = delete;
};
F *pf{new F{}};
struct G {
G() = default;
~G() = delete;
private:
int x;
};
G *pg{new G{}};
都被 GCC 接受。
【问题讨论】:
-
你有什么问题?
-
@Eric ”Is there any open bug report [...]”(我显然没有找到),或者一个回答指出我错了,这个例子,出于某种原因, 实际上格式不正确。
-
@cigien 添加了 LL 标签。
-
@Phil1970 -- 你是对的,如果构造函数抛出异常,编译器必须展开已经构造的任何部分。这不涉及正在构造的对象的析构函数;该析构函数只能在成功构造后使用(想想你必须做些什么来编写一个可以处理部分构造的对象的析构函数)。编译器生成的代码会跟踪到目前为止已构建的内容,因此它只能销毁已成功构建的部分。
标签: c++ gcc language-lawyer compiler-bug