我有一个类型,其析构函数已被显式删除;我想将该类型的实例作为另一个类的成员。
我的期望是,如果没有尝试删除包含类的实例(即包含类的析构函数将无效),应该没问题。
但是,当尝试实例化父类的构造函数时,clang(v3.3)和g ++(v 4.6.3)都会出错。
例如:
class DeletedDtor
{
public:
DeletedDtor() {}
~DeletedDtor() = delete;
};
class MyClass
{
public:
MyClass() = default;
~MyClass() = delete;
private:
DeletedDtor a;
};
int main() {
MyClass *p = new MyClass();
}
在g ++下,这给出了:
test.cpp: In function ‘int main()’:
test.cpp:19:30: error: use of deleted function ‘MyClass::MyClass()’
test.cpp:11:5: error: ‘MyClass::MyClass()’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:11:5: error: use of deleted function ‘DeletedDtor::~DeletedDtor()’
test.cpp:5:5: error: declared here
自己定义MyClass构造函数,而不是让它采用默认实现,不会有任何帮助:
class DeletedDtor
{
public:
DeletedDtor() {}
~DeletedDtor() = delete;
};
class MyClass
{
public:
MyClass();
~MyClass() = delete;
private:
DeletedDtor a;
};
MyClass::MyClass() : a() {}
int main() {
MyClass *p = new MyClass();
}
这给出了编译错误:
test2.cpp: In constructor ‘MyClass::MyClass()’:
test2.cpp:18:24: error: use of deleted function ‘DeletedDtor::~DeletedDtor()’
test2.cpp:5:5: error: declared here
答案 0 :(得分:6)
此行为的一些基本原理:在某种情况下,成员对象的析构函数会在包含对象的析构函数之外自动调用:如果(包含对象的话)的构造函数抛出。在构造函数退出之前,已构造成员和基类子对象的析构函数以相反的构造顺序调用。
答案 1 :(得分:4)
您的问题不正确,构造函数被定义为已删除,因为此类成员的析构函数被定义为已删除,但是,您只需编写
DeletedDtor* d = new DeletedDtor();
并且一切正常(当然没有删除),所以gcc和clang都是正确的。
n3376 12.1 / 8
一个 类X的默认默认构造函数定义为已删除如果:
- 任何直接或虚拟基类或非静态数据成员都有一个删除了析构函数的类型 默认构造函数或默认构造函数无法访问。
答案 2 :(得分:2)
我没有实际C ++标准的副本,但最新的工作草案说:
8.4.3 / 2 [dcl.fct.def.delete]
隐式或明确引用已删除函数的程序, 除了宣布它之外,是不正确的。 [...]
当一个对象被破坏时,隐式调用任何成员对象的析构函数,即使你没有销毁任何对象,仍然会创建一个引用其成员的析构函数的默认析构函数。基于此,你得到的错误对我来说似乎是正确的。
答案 3 :(得分:0)
您不能使用已删除的析构函数来保存该类的实例。但是你可以在DeletedDtor
:
MyClass
class MyClass
{
public:
MyClass() = default;
private:
DeletedDtor* a;
};