我们说我有一些看起来像这样的东西:
struct foo {
~foo() = delete;
}
让我们说我以后会动态分配foo
类型的对象:
foo *f = new foo;
这很好;我假设合成的默认构造函数用于构造由f
表示的对象,但是:
foo f2;
给我一个错误:
尝试使用已删除的功能
那么如果f
的默认构造函数被隐式删除,foo
表示的对象如何被构造?
此外,假设foo
拥有私人成员size_t n
。动态分配n
的{{1}}值是多少,例如foo
表示的值?
答案 0 :(得分:10)
写作时
foo f;
编译器需要能够在最初创建时构造f。由于该变量具有自动存储持续时间(“堆栈上”的奇特C ++术语),因此编译器负责生成代码以进行清理。这需要访问析构函数,但是因为你删除了它,就会出错。
写作时
foo* f = new foo;
您正在创建指向堆栈上foo对象的指针,编译器可以在不访问foo析构函数的情况下销毁指针本身。另一方面,使用new foo创建的对象具有动态存储持续时间,这意味着您承诺手动销毁它。因此,编译器不需要访问析构函数,因此创建步骤很好。那说,如果你再写
delete f;
您应该收到错误,因为该操作确实需要析构函数。
编辑:从您的后续工作中,我的意思是您想知道为什么即使删除了析构函数,仍会生成默认构造函数。我有一个C ++ 14规范草案,在§12.1.4中,它说如下:
类X的默认构造函数是类X的构造函数,可以在没有参数的情况下调用。如果 对于类X没有用户声明的构造函数,隐式声明了没有参数的构造函数 违约(8.4)。隐式声明的默认构造函数是其类的内联公共成员。一个 如果出现以下情况,则将类X的默认默认构造函数定义为已删除:
- X是类似联合的类,其变体成员具有非平凡的默认构造函数,
- 任何没有大括号或等号初始化程序的非静态数据成员都是引用类型,
- 任何const-qualified类型(或其数组)的非变量非静态数据成员,没有任何支撑或 - equal-initializer没有用户提供的默认构造函数,
- X是一个联合,它的所有变体成员都是const限定类型(或其数组),
- X是一个非联合类,任何匿名联合成员的所有成员都是const限定类型 (或其数组),
- 任何直接或虚拟基类,或没有大括号或等号初始化程序的非静态数据成员,都有类 类型M(或其数组)并且M没有应用的默认构造函数或重载决策(13.3) M的默认构造函数导致歧义或在删除或无法访问的函数中 默认的默认构造函数,或
- 任何直接或虚拟基类或非静态数据成员都具有删除了析构函数的类型 或默认的默认构造函数无法访问。
换句话说,删除析构函数对默认构造函数的自动生成没有影响。