File tree Expand file tree Collapse file tree 1 file changed +24
-1
lines changed Expand file tree Collapse file tree 1 file changed +24
-1
lines changed Original file line number Diff line number Diff line change @@ -207,7 +207,30 @@ void f(){
207
207
208
208
我知道你可能有很多疑问,我们既然 catch 接住了异常,为什么还要 throw?以及为什么我们要两个 join()?
209
209
210
- 这两个问题其实也算一个问题,如果代码里抛出了异常,就会跳转到 catch 的代码中,执行 join() 确保线程正常执行完成,线程对象可以正常析构。然而此时我们必须再次 throw 抛出异常,因为你要是不抛出,那么你不是还得执行一个 ` t.join() ` ?显然逻辑不对,自然抛出。至于这个** 函数产生的异常,由调用方进行处理** ,我们只是确保函数 f 中创建的线程正常执行完成,其局部对象正常析构释放。[ 测试代码] ( https://godbolt.org/z/jo5sPvPGE ) 。
210
+ 这两个问题其实也算一个问题,如果代码里抛出了异常,就会跳转到 catch 的代码中,执行 join() 确保线程正常执行完成,线程对象可以正常析构。然而此时我们必须再次 throw 抛出异常,因为你要是不抛出,那么你不是还得执行一个 ` t.join() ` ?显然逻辑不对,自然抛出。
211
+
212
+ 至于这个** 函数产生的异常,由调用方进行处理** ,我们只是确保函数 f 中创建的线程正常执行完成,其局部对象正常析构释放。[ 测试代码] ( https://godbolt.org/z/jo5sPvPGE ) 。
213
+
214
+ > 我知道你可能会想到:“我在 try 块中最后一行写一个 ` t.join() ` ,这样如果前面的代码没有抛出异常,就能正常的调用 join(),如果抛出了异常,那就调用 catch 中的 ` t.join() ` 根本不需要最外部 2 那里的 join(),也不需要再次 ` throw ` 抛出异常”
215
+ >
216
+ > ``` cpp
217
+ > void f (){
218
+ > int n = 0;
219
+ > std::thread t{ func{n},10 };
220
+ > try{
221
+ > // todo.. 一些当前线程可能抛出异常的代码
222
+ > f2();
223
+ > t.join(); // try 最后一行调用 join()
224
+ > }
225
+ > catch (...){
226
+ > t.join(); // 如果抛出异常,就在 这里调用 join()
227
+ > }
228
+ > }
229
+ > ```
230
+ >
231
+ > 你是否觉得这样也可以?也没问题?简单的[测试](https://godbolt.org/z/Wo7Tj95Tz)运行的确没问题。
232
+ >
233
+ > **但是这是不对的**,你要注意我们的注释:“**一些当前线程可能抛出异常的代码**”,而不是 `f2()`,我们的 `try` `catch` 只是为了让线程对象关联的线程得以正确执行完毕,以及线程对象正确析构。并没有处理什么其他的东西,不掩盖错误, `try` 块中的代码抛出了异常, `catch` 接住了,我们理所应当再次抛出。
211
234
212
235
### RAII
213
236
You can’t perform that action at this time.
0 commit comments