Namespaces
Variants

try block

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

try 块中抛出的 异常 有可能被关联的异常处理器捕获处理。

目录

语法

try 复合语句 处理程序序列 (1)
try 构造函数初始化列表  (可选) 复合语句 处理程序序列 (2)
1) 一个 普通 try
2) 一个 函数 try compound-statement 必须是函数体的复合语句组成部分。
compound-statement - 一个 复合语句
handler-seq - 非空的 异常处理程序 序列
ctor-initializer - 成员初始化列表(仅适用于 构造函数

常规 try

一个普通的 try 块是一个 语句

如果从其 复合语句 中抛出异常,该异常将与其 处理序列 中的 处理程序 进行匹配:

void f()
{
    throw 1;     // 不会被下面的异常处理器捕获
    try
    {
        throw 2; // 由关联的异常处理器处理
    }
    catch (...)
    {
        // 处理异常 2
    }
    throw 3;     // 不会被上面的异常处理器捕获
}

函数 try

函数 try 块是一种特殊的 函数体

如果从其 复合语句 构造函数初始化器 (如果存在)抛出异常,该异常将与其 处理程序序列 中的 处理程序 进行匹配:

int f(bool cond)
{
    if (cond)
        throw 1;
    return 0;
}
struct X
{
    int mem;
    X() try : mem(f(true)) {}
    catch (...)
    {
        // 处理异常 1
    }
    X(int) try
    {
        throw 2;
    }
    catch (...)
    {
        // 处理异常 2
    }
};

具有静态 存储期 的对象在其析构函数中抛出的异常,或具有静态存储期的 非块作用域变量 关联对象在其构造函数中抛出的异常,不会被 main 函数 上的函数 try 块捕获。

在线程存储期对象的析构函数中,或在线程存储期非阻塞变量关联对象的构造函数中抛出的异常,不会被线程初始函数的函数 try 块捕获。

(since C++11)

从函数 try 块的 处理器 复合语句 末尾流出,等同于从该函数 try 块的 compound - statement 末尾流出,除非该函数是构造函数或析构函数(见下文)。

构造函数与析构函数 try

对于类 C ,若其构造函数或析构函数定义的函数体为函数 try 块,且在 C 的子对象初始化或析构期间分别抛出异常,该异常也将与函数 try 块的 handler-seq  中的 异常处理器 进行匹配:

int f(bool cond = true)
{
    if (cond)
        throw 1;
    return 0;
}
struct X
{
    int mem = f();
    ~X()
    {
        throw 2;
    }
};
struct Y
{
    X mem;
    Y() try {}
    catch (...)
    {
        // 处理异常1
    }
    ~Y() try {}
    catch (...)
    {
        // 处理异常2
    }
};

在构造函数或析构函数的函数 try 块处理程序中,引用该对象的任何非静态成员或基类将导致未定义行为。

如果在构造函数的函数 try 块的处理器中出现 return 语句 ,则程序是非良构的。

如果控制到达构造函数或析构函数的函数 try 块处理程序末尾,将重新抛出 当前正在处理的异常

控制流

复合语句 try 块是一个 控制流受限语句

void f()
{
    goto label;     // 错误
    try
    {
        goto label; // 正确
        label: ;
    }
    catch (...)
    {
        goto label; // 错误
    }
}

一个 跳转语句 goto break return continue )可用于将控制权转移出 try 块(包括其异常处理程序)。当这种情况发生时,在 try 块中声明的每个变量将在直接包含其声明的上下文中被销毁:

try
{
    T1 t1;
    try
    {
        T2 t2;
        goto label; // 先销毁 t2,然后销毁 t1
    }
    catch(...)
    {
        // 当销毁 t2 时抛出异常则执行此处
    }
}
catch(...)
{
    // 当销毁 t1 时抛出异常则执行此处
}
label: ;

关键词

try

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用标准 发布时行为 正确行为
CWG 98 C++98 switch 语句可以将控制流转移
复合语句 try 块内部
禁止此行为
CWG 1167 C++98 未说明析构函数的函数 try 块是否
会捕获基类或成员析构函数抛出的异常
此类异常
会被捕获

参见