Java 和 C#,可能还有许多其他语言,都有一个预定义的异常类,当在不应该使用 null 参数时抛出该异常类。C ++中有类似的东西吗?如果没有,我是否可以使用另一个预定义的异常,或者我应该定义自己的异常?
7 回答
取消引用 NULL 指针在 C++ 中是未定义的行为——这意味着代码看起来可以工作。不保证会抛出异常。您可以使用
异常(为其提供有意义的值 - "p is NULL"
),但您必须自己进行检查。
通常,在 C++(或 C)中,您永远不会取消引用 NULL 指针。这样做有未定义的行为(可能是我所知道的任何实现的段错误,但根据标准可能会发生任何事情)。在其他语言中这可能也是一件坏事,但我不知道这些足以断言。
最好是防止这种情况发生,而不是试图从中恢复(无论如何这在 C 或 C++ 中都做不到)。
防止一些相关的程序员错误的常用模式是使用assert()
内部函数体,例如:
int foo(int* myint)
{
// Ensure myint is not NULL
assert(myint);
// Do something with myint
(*myint)++;
return *myint;
}
此类assert()
调用在发布版本中完全被忽略,因此在生产中没有成本。他们只是帮助发展。在调试构建时,如果不满足条件,程序会立即中止并显示非常明确的错误消息。通过调试器运行它,您可以轻松检查调用堆栈以调查确切原因。
C++ 中没有用于取消引用 NULL 指针的标准例外。
如果你想要它,你可以自己实现它。在 UNIX 上设置 SIGSEGV 信号处理程序并从处理程序中抛出异常。在 Windows 上,使用 _set_se_translator() API 安装“结构化异常”处理程序。
NullReferenceException
FTR,在 C# 中,除非您想被队友刺伤,否则您不会将s 用于任何事情。有一个ArgumentNullException
用于拒绝空参数的替代方法。NRE 是由运行时抛出的,而不是你。
但请注意,与断言相比,这并没有真正的优势,因为您不应该捕获其中之一:如果它们被抛出,则表明它们存在错误。这些是 Eric Lippert 所说的愚蠢的异常,它们是你自己的错误,你的代码不应该专门对它们做任何事情。
在几乎所有涉及错误使用空指针(尤其是取消引用它)的情况下,C++ 标准只是简单地保留了未定义的行为。没有提供特定的异常类型(也不会抛出异常)。
不过,我想到了这个规则的一个可能的例外。std::function
,这是一个可用于包装函数的 C++11 标准库模板,可以分配一个空指针:
std::function<void(int)> func = nullptr;
然后,如果您尝试通过执行func(arg);
for some argument来调用由它包裹的函数arg
,它将引发std::bad_function_call
异常。
当然,这并不完全等同于其他语言的空指针异常,因为它的普遍适用性要差得多。
在 C++ 下,取消引用空指针将导致未定义的行为,这主要以分段错误结束应用程序。在 Visual Studio 下,您可以使用结构化异常处理 (SEH) 等扩展,这些扩展允许捕获空指针取消引用。
您可以将指针包装在模板类中,该类为指针提供有限的接口。每当您访问指针并抛出异常时,它都可以进行 nullptr 检查。