17

也许我越来越生疏了(最近一直在用 Python 写)。

为什么这不编译?

if ( (int i=f()) == 0)

没有()周围的int i=f()我得到另一个更合理的错误i不是布尔值。但这就是为什么我首先想要括号!

我的猜测是使用括号使其成为表达式,并且表达式中不允许声明语句。是这样吗?如果是,它是 C++ 的语法怪癖之一吗?

顺便说一句,我实际上是在尝试这样做:

if ( (Mymap::iterator it = m.find(name)) != m.end())
    return it->second;
4

4 回答 4

38

您可以在 C++ 中的语句中声明一个变量,if但它仅限于直接初始化使用,并且需要转换为布尔值:

if (int i = f()) { ... }

C++没有任何可以被描述为“声明表达式”的东西,即[sub-]表达式声明一个变量。

实际上,我只是在标准中查找了该子句,根据 6.4 [stmt.select] 第 1 段支持两种形式的初始化:

...
condition:
   expression
   attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
   attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list
...

也就是说,也可以这样写:

if (int i{f()}) { ... }

显然,这只适用于 C++2011,因为 C++2003 没有大括号初始化。

于 2012-01-22T13:46:42.497 回答
20

范围有问题。

考虑以下代码:

if ((int a = foo1()) || (int b = foo2()))
{
    bar(b);
}

b 是否在块内声明?如果foo1()返回真呢?

于 2012-01-22T13:45:16.953 回答
5

您可以在 if 语句(或 for 或 while)中声明变量,但只能在外括号块中声明,并且它需要能够转换为 bool。

您的猜测基本上是正确的,这是不允许的,因为

(int i = 42;)

不是带有初始化的有效声明。

你需要额外的一行,

Mymap::iterator it;
if ( (it = m.find(name)) != m.end())
    return it->second;

但是最好写

Mymap::iterator it = m.find(name);
if ( it != m.end() ) 
    return it->second;

如果你真的想要这条线,你可以把这return条线放在if后面,至少对我来说这不会损害可读性,但其他人可能会看到不同。

如果您真的非常想声明一个迭代器并将其用作if条件中的布尔值,您可以这样做

if ( struct { int it; operator bool() { return it != m.end; } } s = { m.find(name) } )
    return s.it->second;

但我认为这是有害的;-)

于 2012-01-22T14:04:06.013 回答
0

写不出来是真的

if ( (int i=f()) == 0)

但你可以完美地写

if ( int i=f())

因此,您可以使用&&运算符在一个语句中执行这两个操作,例如

if ( int i=1 && (i=f()) == 0)

i应该使用 0 以外的任何值进行初始化,并且如果您的编译器应用从左到右的评估,它应该是第一个条件。

但不幸的是,这不适用于第二个示例所要求的迭代器。

于 2015-01-09T19:28:00.120 回答