如果条件在内部声明变量有什么问题?

时间:2012-01-22 13:40:38

标签: c++ syntax variable-declaration

也许我变得生疏了(最近用Python编写)。

为什么不编译?

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

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

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

顺便说一下,我其实是在尝试这样做:

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

4 个答案:

答案 0 :(得分: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没有大括号初始化。

答案 1 :(得分:20)

范围有问题。

请考虑以下代码:

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

是否在块内声明了?如果foo1()返回true,该怎么办?

答案 2 :(得分: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条件下使用它作为bool,你可以做

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

但我认为这有害; - )

答案 3 :(得分:0)

你无法写

这是真的
if ( (int i=f()) == 0)

但你可以完美地写

if ( int i=f())

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

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

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

但不幸的是,如果您的第二个例子要求使用迭代器,则不适用。