Namespaces
Variants

try block

From zh.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 块是否
会捕获基类或成员析构函数抛出的异常
此类异常
会被捕获

参见