我正在教自己使用异常安全模式进行编程的技巧;)我想知道解除引用指针是否会引发异常?我认为所有C ++程序员都知道所有保证不会抛出的操作会很有帮助,所以如果有人能编写这样的列表,我将非常感激。
答案 0 :(得分:11)
取消引用简单指针(T*
)可能会导致 未定义行为 指针指向的位置。 UB 的本质是 结果可能是 ,包括但不限于C ++异常。人们可以想象一个实现可以检查访问指针并抛出异常。但是,我怀疑C ++的这种实现是否会存在(如果你可以节省运行时的开销,为什么要使用C ++?)并且大多数平台上的常见行为要么混乱(如果有问题的内存被分配了)进程)或 崩溃 。在某些平台上,有一些方法可以拦截此类崩溃(例如Windows'结构化异常)。
但是,一元operator*()
可能 重载 ,通常用于智能指针和迭代器。这样的实现当然可以执行它们的实现者想要的任何事情,包括但不限于抛出异常。但同样由于运行时开销,常见的智能指针实现只检查调试版本(通常使用某种形式的断言),但不在发布版本中。 (一个值得注意的例外是最近的Visual C ++实现中的迭代器,它为这种不寻常的行为提供了相当多的热量。)
C ++中有一个非常强大的传统,可以区分程序员可能阻止的 错误 (比如访问数组越界)和 程序员无法阻止的错误 (如网络连接死亡)。对于原始速度,前者通常会导致 UB ,因为每次检查它们都会导致性能下降。程序员可以在适当和必要的地方进行检查
您可以在标准库的异常层次结构的定义中看到这种区别,该异常层次结构分为可预防的std::logic_error
和不可预防的std::runtime_error
。
答案 1 :(得分:1)
取消引用无效指针是未定义的行为,然后实现可以将其定义为抛出异常。这在C ++中非常罕见,尽管它是其他一些语言的规则。
您可以使用std::signal( my_handler, SIGSEGV );
捕获内存访问异常,但这仍然取决于平台支持,并且标准不允许您将其转换为C ++异常。
据我所知,微软有自己的“托管”异常或其他一些例外,这些异常可能会被这种机制捕获并在C ++约定中重新引发。或许那是被禁止的;我不知道。
答案 2 :(得分:0)
解除引用发生在运行时,并且处于非常低的级别(程序集/机器级别),因此它不能抛出任何东西,但它会引发异常,例如linux / unix上的EXCEPTION_ACCESS_VIOLATION
或SegFault。
(假设正在使用原始指针)
答案 3 :(得分:0)
如果它是一个简单的指针(而不是某些autopointer对象或迭代器等),则解除引用的行为不能抛出异常,因为取消引用它本身不会做任何事情。在编译过程中,取消引用指针只是告诉编译器编写一个指令,该指令对指针指向的内容执行某些操作。如果指针无效并且您尝试使用解除引用的表达式写入它,那么它肯定会(或应该)错误输出。
举个例子:
int *p = 0xFFFFFFFF; // Invalid pointer
*p; // Dereferenced, but since it doesn't do anything there's no error
*p = 0; // Dereferenced write, so it will halt and catch fire