最好开始使用代码来理解这个
#include "Hello1.h"
#include "Hello2.h"
int main(int argc, char ** argv)
{
// Hello1 and Hello2 are derevied classes of Hello
// And there constructor throws an exception
Hello * h;
try
{
if (argv[1][0]=='1')
h = new Hello1;
else
h = new Hello2;
}
catch (std::exception ex) { /*print error*/ }
delete h;
}
如果Hello1
和Hello2
引发异常,则 segfault 。但是,如果我添加
Hello h = NULL;
有效!!!
Hello是一个带有构造函数的类,它抛出异常
所有我能想到的是构造函数中的异常从内存中删除对象!为什么谁...谁解释!请。
答案 0 :(得分:6)
但是,如果我添加
Hello h = NULL;
,它就可以了!为什么谁...谁解释!请。
这是因为operator delete
在指针为null
时什么都不做。预计什么都不做,这是标准行为。 C ++ 11标准的第3.7.4.2段规定:
[...]的价值 提供给释放函数的第一个参数可以是空指针值;如果是的话,如果解除分配 功能是标准库中提供的功能,呼叫无效。 [...]
如果它不是null
,另一方面,operator delete
将尝试删除hello
指向的对象,并且因为指针未初始化(因为构造投掷并控制在分配给hello
之前转移到异常处理程序中,您得到未定义的行为。
根据第5.3.5 / 2段:
[...]在第一个备选方案(删除对象)中,
delete
的操作数的值可能是空指针 value,指向前一个new-expression创建的非数组对象的指针,或指向子对象的指针(1.8) 表示这种对象的基类(第10条)。 如果不是,则行为未定义。 [...]
答案 1 :(得分:1)
为什么谁......解释!请。
如果Hello
的构造函数抛出h
从未初始化 - delete
尝试从未定义的未初始化变量和行为中读取。
我建议使用智能指针。
答案 2 :(得分:0)
delete
会抛出异常。正如其他人所指出的,如果您尝试删除设置为delete
null
将不会抛出
据我所知, new
除非你失去记忆,否则永远不会抛出。
所以会发生argv[1]
不是'1'
,这意味着h指向未知的东西,这会使delete
抛出异常