我在C++中有以下代码:
#include <iostream>
class Number
{
public:
virtual void foo(){std::cout << "Number foo\n";};
Number (){ std::cout << "Number ctor" << std::endl;}
virtual ~Number(){ std::cout << "Number dtor" << std::endl;}
};
class Complex : public Number
{
public:
virtual void foo(){std::cout << "Complex foo\n";};
Complex (double r=0, double i=0) : _r (r), _i (i)
{ std::cout << "Complex ctor" << std::endl; };
virtual ~Complex(){ std::cout << "Complex dtor" << std::endl;}
private:
double _r,_i;
};
int main()
{
Number *numArr = new Complex [2];
delete [] numArr;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当析构函数声明为虚拟时,应用程序将退出分段错误.当它没有被声明为虚拟时,会调用Number类析构函数(这很明显......).但是,当析构函数被声明为虚拟时,当我删除Complex类中的双精度时,没有分段错误,并且析构函数以预期的顺序(Complex,Number)被调用,所以我猜问题是相关的对于物体的大小,有人可以给我一个解释吗?谢谢,阿米特.
Number *numArr = new Complex [2];
delete [] numArr;
Run Code Online (Sandbox Code Playgroud)
实际上,删除操作会调用未定义的行为.
§5.3.5/ 3说,
在第一个替代(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.)
它的实际含义是:
Number *object= new Complex();
delete object; //well-defined
//BUT
Number *array = new Complex[N];
delete [] array; //undefined
Run Code Online (Sandbox Code Playgroud)