为什么try..catch块需要括号?

Bid*_*dou 43 c++ syntax try-catch

而在if等中的其他语句中,如果块中只有一条指令,则可以避免使用大括号,而不能使用try ... catch块执行此操作:编译器不会购买它.例如:

try
    do_something_risky();
catch (...)
    std::cerr << "Blast!" << std::endl;
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,g ++只是说它在do_something_risky()之前需要一个'{'.为什么这种行为的差异尝试...捕获,比如说,如果......其他?

谢谢!

Jus*_*ner 13

直接来自C++规范:

try-block:
    try compound-statement handler-seq
Run Code Online (Sandbox Code Playgroud)

如你所见,所有人都try-block期待着compound-statement.根据定义,复合语句是用大括号包装的多个语句.

将复合语句中的所有内容都确保为try-block生成新范围.在我看来,这也使得一切都更容易阅读.

您可以在C++语言规范的第359页上自行查看

  • 尊敬的是,这个答案是无益的.标准要求它是不言而喻的.问题不是"尝试捕获块需要括号",而是"为什么......". (16认同)
  • *"使复合语句中的所有内容都能确保为try-block生成新的作用域."*C++中的作用域不依赖于大括号.同样在`if(n> 0)std :: vector <float> v(n);`中,在右括号后面打开一个新的作用域(只包含`v`),并以分号结束. (9认同)
  • 问:为什么草绿?答:直接来自物理学:`green = 510 nm`.正如您所见,草在光谱仪上产生510 nm的尖峰.根据定义,510nm是绿色.在510 nm处有一个尖峰,确保草是绿色的.在我看来,这也让我看起来更容易一些.您可以到外面看草地自行检查. (5认同)

R S*_*hko 10

不知道为什么,但一个好处是没有悬空捕捉问题.看看dangling-else是否存在大括号是可选的歧义.


Ale*_*dro 7

try-block的语法是:

try compound-statement handler-sequence
Run Code Online (Sandbox Code Playgroud)

其中handler-sequence是一个或多个处理程序的序列,具有以下语法:

catch (type-specifier-seq declarator) compound-statement
catch (...) compound-statement
Run Code Online (Sandbox Code Playgroud)

这与控制语句等其他语句不同(if,while,for等).这些的语法是:

if (condition) statement-true else statement-false  
while (condition) statement
for (init-statement; condition; iteration_expression) statement
etc.
Run Code Online (Sandbox Code Playgroud)

现在,问题是为什么try-block而不是单个语句需要复合语句?

想想这段代码:

int main()
{
  // before try-statement.

  try g(); catch (std::runtime_error e) handleError(e);

  // after try-statement.
}
Run Code Online (Sandbox Code Playgroud)

我知道,按值捕获是一种不好的做法(例如可能的对象切片等),但我这样做是为了防止讨论异常的存储持续时间并使其易于推理.

现在想想,关于'e'的存储持续时间和联系.您期望的是,'e'只能在调用handleError函数之前引用,但在调用完成后才会引用.它应具有自动存储持续时间,并且在此"范围"中没有链接.这可能通过隐式定义局部作用域来完成,就像在其他语句中一样,但是使异常声明看起来像一个函数参数可能是一个更好的主意.所以需要块(复合语句).Se bellow.

现在考虑一下尝试和之后的声明.没有理由使用关键字try那里,没有理由使用复合语句,但语法可能会变得模糊和复杂.

这就是Stroustrup在C++的异常处理中所说的:

It might be possible to simplify the

try { ... } catch (abc) { ... }

syntax  by  removing  the  apparently  redundant try keyword,
removing  the  redundant  parentheses, and by allowing a handler
to be attached to any statement and not just to a block.  For 
example, one might allow:

void f()
{
  g(); catch (x1) { /* ... */ }
}

as an alternative to - 28 -

void f()
{
  try { g(); } catch (x1) { /* ... */ }
}

The added notational convenience seems insignificant and may not
even be convenient. People seem to prefer syntactic constructs that
start with a prefix that alerts them to what is going on, and it may
be easier to generate good code when the try keyword is required.  
Run Code Online (Sandbox Code Playgroud)

经过更详细的解释:

Allowing exception handlers to be attached to blocks only and not to
simple statements simplifies syntax analysis (both for humans and
computers) where several exceptions are caught and where nested
exception  handlers are considered (see Appendix E). For example,
assuming that we  allowed handlers to be attached to any statement
we could write:

try try f(); catch (x) { ... } catch (y) { ... } catch (z) { ... }

The could be interpreted be in at least three ways:

try { try f(); catch (x) { ... } } catch (y) { ... } catch (z) { ... }
try { try f(); catch (x) { ... } catch (y) { ... } } catch (z) { ... }
try { try f(); catch (x) { ... } catch (y) { ... } catch (z) { ... } }

There seems to be no reason to allow these ambiguities even if there
is a trivial and systematic way for a parser to chose one
interpretation over another. Consequently, a { is required after a
try and a matching } before the first of the associated sequence of
catch clauses.
Run Code Online (Sandbox Code Playgroud)

正如Stroustrup所说,没有括号,声明可能意味着不同的东西取决于规则,你可能需要用括号来澄清内涵.在Stroustrup的例子中,我们可以使用if语句制作一些看起来很复杂的东西吗?当然我们可以这样,例如:

if (c1) if (c2) f(); else if (c3) g(); else h();
Run Code Online (Sandbox Code Playgroud)

这实际上相当于:

if (c1) { if (c2) f(); else { if (c3) g(); else h(); } }
Run Code Online (Sandbox Code Playgroud)

但我认为这比try-block的问题要少.if-statament有两种语法:

if (condition) statement-true
if (condition) statement-true else statement-false
Run Code Online (Sandbox Code Playgroud)

因为有时候不采取其他行动是有道理的.但是没有catch-clause的try-block就没有意义.正如Stroustrup所说,'try'可以省略但不实用,但是如果指定了try-block,则catch-clause不能.除此之外,可能存在多个与同一个try-block相关的catch,但只有一个基于依赖于catch-clauses的异常类型和顺序的规则执行.

现在,如果if-else的语法更改为:

if (condition) compound-statement-true else compound-statement-false
Run Code Online (Sandbox Code Playgroud)

那么,你必须写if-else像这样:

if (c1) { f(); } else { if (c2) { g(); } else { h(); } }
Run Code Online (Sandbox Code Playgroud)

看到没有'elseif'关键字,'else if'没有特殊语法.我认为即使是"总是戴上牙套"的防守者也不喜欢这样写,而是写下来:

if (c1) { f(); } else if (c2) { g(); } else { h(); }
Run Code Online (Sandbox Code Playgroud)

我认为这不是一个强有力的理由来定义上面的语法,并在语言中引入'elseif'关键字或为'else if'定义一个特殊的语法.

  • 这些都不是很有说服力.最后一个引用中的示例与`if-else`的情况没有什么不同:`else`转到最近的`if`,如果你想改变它 - 使用`{}`.我不明白为什么这条规则不能用'try-catch`采用. (2认同)

vpi*_*833 6

阅读此链接.大多数原因似乎是关于管理在真实异常情况下需要创建和销毁的对象的范围和分配.

所以,我的猜测是,C++的语法编写者要求g ++(或任何符合C++编译器的标准)的作者为最坏的情况做准备,而g ++作者似乎已经这样做了.

  • [此链接](http://www.kuzbass.ru:8086/docs/isocpp/except.html)似乎被打破了. (2认同)

MSa*_*ers 5

为什么?安全性和向后兼容性之间的权衡.

从if ......中得到的教训表明,需要括号可以消除错误.现在,ISO C++人员强烈倾向于向后兼容C,因此他们没有更改if ... else的C语法.但是新构造需要大括号来划分受控块,因为它们不会出现在旧C代码中,因此向后兼容性不是问题.

  • 如果那是原因,那么我要感谢我的“ if()if()else;”的向后兼容性。结构体。我喜欢这些东西,并且非常有能力适当地使用它们。对于人类来说,肯定是有可能的。(当然,无论任何实际的程序员有多胜任,给予足够多的知识来绞尽脑汁也是C ++的精神;因此,如果很难确认这确实是本书的基本原理,我会感到有些惊讶。尝试捕获的情况。) (2认同)

Pau*_*han 3

嗯,首先,语法就是这样运作的。

其次,我认为目标是强制为异常块生成新的范围(如果我错了,请纠正我)。