iam*_*ind 15 c++ undefined-behavior virtual-destructor
这个问题不同于' 何时/为什么要使用virtual析构函数?".
struct B {
virtual void foo ();
~B() {} // <--- not virtual
};
struct D : B {
virtual void foo ();
~D() {}
};
B *p = new D;
delete p; // D::~D() is not called
Run Code Online (Sandbox Code Playgroud)
问题:
~D()不会被称为肯定)吗?~D()是空的怎么办 它会以任何方式影响代码吗?new[]/ delete[]with时B* p;,~D()无论virtual析构函数是什么,都肯定不会被调用.它是未定义的行为还是定义明确的行为?Alo*_*ave 19
何时/为什么要使用虚拟析构函数?
遵循Herb Sutters 指南:
基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的
这可以被归类为未定义的行为(我们知道~D()肯定不会被调用)?
根据标准,它是未定义的行为,这通常导致Derived类析构函数未被调用并导致内存泄漏,但是在未定义行为的效果之后进行推测是无关紧要的,因为标准没有在这方面保证任何东西.
C++ 03标准:5.3.5删除
5.3.5/1:
delete-expression运算符销毁由new-expression创建的派生程度最高的对象(1.8)或数组.
delete-expression
::: opt delete cast-expression
:: opt delete [] cast-expression
5.3.5/3:
在第一个替代(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为是未定义的.73)
如果~D()是空的怎么办 它会以任何方式影响代码吗?
仍然是根据标准的未定义行为,派生类析构函数为空可能只是使您的程序正常工作,但这又是特定实现的实现定义方面,从技术上讲,它仍然是未定义的行为.
请注意,这里没有gaurantee没有使派生类析构函数virtual不会导致对派生类析构函数的调用,并且这个假设是不正确的.根据标准,一旦您在未定义的行为领域交叉,所有投注都将被取消.
请注意他标准中关于未定义行为的内容.
C++ 03标准:1.3.12未定义的行为[defns.undefined]
行为,例如在使用错误的程序结构或错误数据时可能出现的行为,本国际标准没有规定任何要求.当本国际标准忽略对行为的任何明确定义的描述时,也可能预期未定义的行为.[ 注意:允许的未定义行为包括完全忽略不可预测的结果,在翻译或程序执行期间以环境特征的文件表示(有或没有发出诊断消息),终止翻译或执行(发布诊断信息).许多错误的程序结构不会产生未定义的行为; 他们需要被诊断出来.]
如果仅调用派生的析构函数,则由上面引用中的粗体文本控制,对于每个实现显然都是开放的.