29 c++ destructor c++11
请考虑以下代码:
#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>
struct A
{
A(){ };
~A() = delete; //{ std::cout << "~A::A()" << std::endl; };
};
struct B: A
{
B(){ };
};
B *b = new B;
int main(){ }
Run Code Online (Sandbox Code Playgroud)
vso*_*tco 16
问题是B编译器删除了构造函数,否则默认定义将是错误的.这是因为A没有析构函数,以及默认的构造函数B无法构造一个B从A如果A不能被破坏.如果用g ++编译,那就是你得到的错误:
note: 'B::B()' is implicitly deleted because the default definition would be ill-formed:
或者铿锵++:
error: call to implicitly-deleted default constructor of 'B'
如果你B(){}明确地声明构造函数,那么它会因为删除而导致因为它无法破坏A部分而引发抱怨.在编译时检查隐藏其父级的能力,因此您收到错误.BA::~A()BA
这个问题的+1.看来你不能从带有删除的析构函数的类继承(然后使用实例),尽管这是我第一次碰到这个问题.
T.C*_*.C. 15
该标准的适用部分是(引用N4140):
§12.4[class.dtor]/p11:
如果调用析构函数或在5.3.4和12.6.2中指定,则可能会调用析构函数.如果可能调用的析构函数被删除或无法从调用的上下文访问,则程序格式不正确.
§12.6.2[class.base.init]/p10:
在非委托构造函数中,可能会调用每个可能构造的类类型子对象的析构函数(12.4).[ 注意:此规定确保在抛出异常时可以为完全构造的子对象调用析构函数(15.2).- 结束说明 ]
§12[特殊]/p5:
对于一个类,它的非静态数据成员,它的非虚拟直接基类,如果该类不是抽象的(10.4),它的虚拟基类被称为它可能构造的子对象.
由于A是一个非虚拟直接基B和因此潜在的子对象构成的B,它的析构潜在调用中B::B(),并自该析构函数被删除,是形成不良的节目.
另见CWG第1424期.
Jam*_*nze 11
至于是什么,我认为是你的基本的问题:你为什么不能建立一个B,尽管它只是析构函数的A不存在:在构造函数B,编译器会自动生成代码调用析构函数A,如果有一个例外.如果A要用作基类,它必须具有可访问的析构函数(公共或受保护的).
当然,在你的情况下,构造函数B不能抛出,因此
A::~A()永远不会被调用.但编译器无法始终确定是否是这种情况,并且标准不要求它甚至尝试.编译器必须假设B::B()可能抛出的体(在完全构造之后A).即使它可以确定B::B()不能抛出,并且不生成调用析构函数的代码A,这也是一种优化,不允许改变代码的合法性.
小智 5
基于第一个代码:
#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)
请尝试以下方法:
#include <iostream>
struct A
{
A(){ };
~A(){ std::cout << "~A::A()" << std::endl; };
};
struct B: A { };
int main(){
B b;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3470 次 |
| 最近记录: |