这一行代码崩溃是因为对无效指针进行了解引用。在C++中,这不会引发异常,而是未定义的行为。
在C++中不存在
空指针异常,不像Java会抛出空指针异常。相反,对无效指针进行解引用将导致未定义的行为。未定义的行为并不总是意味着崩溃,但如果崩溃了,那就是幸运的。
语言概述:
最后和RAII
C++和Java之间最显著的区别之一是Java支持
finally
语句。无论前面的
catch
块是否执行,都会执行
finally
块中的代码。例如:
try
{
}
catch (SomeException e)
{
}
finally
{
}
finally语句的目的是允许程序员在该点进行清理,即释放套接字、关闭文件句柄等等。尽管Java运行垃圾收集器,但垃圾收集只适用于内存,而不适用于其他资源。仍然有时需要
手动处理资源。现在C++没有
finally
语句,因此建议使用该语言的用户遵守RAII原则(资源获取即初始化)。Stroustrup在这里对其进行了解释:
http://www.stroustrup.com/bs_faq2.html#finally。我更喜欢称其为
资源销毁即释放
,但基本上当您的对象超出范围并调用析构函数时,该析构函数应释放对象维护的任何资源。
例如,C++11x提供了std::unique_ptr来管理这个问题:
void foo()
{
std::unique_ptr<T> t(new T)
try
{
}
catch (...)
{
}
}
使用new
分配的资源将在函数结束时被删除。
捕获所有语句
因为Java中的所有异常都继承自一个共同的基类Exception
,如果你想让你的catch子句捕获任何异常,那么设置它就像这样:
catch (Exception e)
{
}
C++中没有限制可以抛出什么异常,也没有所有异常的共同基类。标准惯例是通过继承std::exception来形成自定义的异常类,但语言不强制执行此操作。相反,有一个特殊的语法可以捕获所有异常:
catch (...)
{
}
未处理的异常
这是另一个语言行为不同的领域。在C++中,未被捕获的抛出异常将调用std::terminate。std::terminate的默认行为是调用abort,生成SIGABRT并停止整个程序。
在Java中,行为是打印堆栈跟踪并终止发生未捕获异常的线程。但是,由于Java程序员可能提供了UncaughtException处理程序,因此行为可能与终止线程的默认行为有所不同。