请考虑以下代码:
#include <iostream>
struct A
{
A(){ };
~A(){ std::cout << "~A::A()" << std::endl; };
};
struct B: A { };
B *b = new B; //Doesn't produce any side-effect.
int main(){ }
Run Code Online (Sandbox Code Playgroud)
程序不会产生任何输出,这意味着不会调用析构函数.但是如果我们用说明delete符替换析构函数的主体,程序甚至不会编译.
#include <iostream>
struct A
{
A(){ };
~A() = delete; //{ std::cout << "~A::A()" << std::endl; };
};
struct B: A { };
B *b = new B; //Error: use of deleted function
int main(){ }
Run Code Online (Sandbox Code Playgroud)
由于调用了删除的功能.那是在这种情况下被调用的析构函数.为什么会有这样的差异?
即使我们明确定义了B构造函数,它也不会起作用:
#include <iostream> …Run Code Online (Sandbox Code Playgroud) 请考虑以下文本:
[C++11: 12.4/11]:隐式调用析构函数
- 对于在程序终止时具有静态存储持续时间(3.7.1)的构造对象(3.6.3),
- 对于在线程出口处具有线程存储持续时间(3.7.2)的构造对象,
- 对于具有自动存储持续时间(3.7.3)的构造对象,当创建对象的块退出时(6.7),
- 对于临时对象的生命周期结束时构造的临时对象(12.2),
- 对于由new-expression(5.3.4)分配的构造对象,通过使用delete-expression(5.3.5),
- 在几种情况下由于处理异常(15.3).
如果声明了类类型的对象或其数组,并且在声明的点处无法访问类的析构函数,则程序是不正确的.也可以显式调用析构函数.
那为什么这个程序编译成功呢?
#include <iostream>
struct A
{
A(){ };
~A() = delete;
};
A* a = new A;
int main() {}
// g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Run Code Online (Sandbox Code Playgroud)
GCC是否只是宽容?
我倾向于这样说,因为它拒绝了以下内容,但标准似乎没有特定于删除继承层次结构中的析构函数的特定规则(唯一松散相关的措辞与默认默认构造函数的生成相关):
#include <iostream>
struct A
{
A() {};
~A() = delete;
};
struct B : A {};
B *b = new B; // error: use of deleted function
int main() {}
Run Code Online (Sandbox Code Playgroud)