C++,'if'中的变量声明表达
这是怎么回事?
if(int a = Func1())
{
// Works.
}
if((int a = Func1()))
{
// Fails to compile.
}
if((int a = Func1())
&& (int b = Func2()))
)
{
// Do stuff with a and b.
// This is what I'd really like to be able to do.
}
2003 标准中的第 6.4.3 节解释了选择语句条件中声明的变量如何将其范围扩展到该条件控制的子语句的末尾。但我没有看到它在哪里说不能在声明两边加上括号,也没有说每个条件只能有一个声明。
即使在只需要条件中的一个声明的情况下,这种限制也是令人烦恼的。考虑一下这一点。
bool a = false, b = true;
if(bool x = a || b)
{
}
如果我想输入 x 设置为 false 的“if”主体范围,则声明需要括号(因为赋值运算符的优先级低于逻辑 OR),但由于不能使用括号,因此需要在外部声明 x主体,将该声明泄漏到比预期更大的范围。显然这个例子很简单,但更现实的情况是 a 和 b 是返回需要测试的值的函数,
这就是我想要做的不符合标准的事情,或者我的编译器只是破坏了我的球(VS2008 )?
What's going on here?
if(int a = Func1())
{
// Works.
}
if((int a = Func1()))
{
// Fails to compile.
}
if((int a = Func1())
&& (int b = Func2()))
)
{
// Do stuff with a and b.
// This is what I'd really like to be able to do.
}
Section 6.4.3 in the 2003 standard explains how variables declared in a selection statement condition have scope that extends to the end of the substatements controlled by the condition. But I don't see where it says anything about not being able to put parenthesis around the declaration, nor does it say anything about only one declaration per condition.
This limitation is annoying even in cases where only one declaration in the condition is required. Consider this.
bool a = false, b = true;
if(bool x = a || b)
{
}
If I want to enter the 'if'-body scope with x set to false then the declaration needs parenthesis (since the assignment operator has lower precedence than the logical OR), but since parenthesis can't be used it requires declaration of x outside the body, leaking that declaration to a greater scope than is desired. Obviously this example is trivial but a more realistic case would be one where a and b are functions returning values that need to be tested
So is what I want to do non-conformant to the standard, or is my compiler just busting my balls (VS2008)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
从 C++17 开始,您尝试做的事情终于可能
:使用
;
代替,
来分隔声明和实际条件。As of C++17 what you were trying to do is finally possible:
Note the use of
;
of instead of,
to separate the declaration and the actual condition.我想你已经暗示了这个问题。编译器应该如何处理这段代码?
“&&”运算符是短路逻辑 AND。这意味着如果第一部分
(1==0)
结果为 false,则不应评估第二部分(bool a = false)
,因为它众所周知,最终答案将是错误的。如果(bool a = false)
未计算,那么稍后使用a
的代码该怎么办?我们是否会不初始化变量并使其保持未定义状态?我们会将其初始化为默认值吗?如果数据类型是类并且这样做会产生不良副作用怎么办?如果您使用一个类而不是bool
,并且它没有默认构造函数,因此用户必须提供参数,那我们该怎么办?这是另一个例子:
看起来您发现的限制似乎完全合理 - 它可以防止此类歧义的发生。
I think you already hinted at the issue. What should the compiler do with this code?
The "&&" operator is a short-circuit logical AND. That means that if the first part
(1==0)
turns out to be false, then the second part(bool a = false)
should be not be evaluated because it is already known that the final answer will be false. If(bool a = false)
isn't evaluated, then what to do with code later on that usesa
? Would we just not initialize the variable and leave it undefined? Would we initialize it to the default? What if the data type was a class and doing this had undesirable side effects? What if instead ofbool
you used a class and it had no default constructor such that the user must provide parameters - what do we do then?Here's another example:
Seems like the limitation you have found seems perfectly reasonable - it prevents these kinds of ambiguities from happening.
if
或while
语句中的条件可以是表达式,也可以是单个变量声明(带有初始化) )。您的第二个和第三个示例既不是有效的表达式,也不是有效的声明,因为声明不能构成表达式的一部分。虽然能够编写像第三个示例这样的代码会很有用,但它需要对语言语法进行重大更改。
6.4/1 中的语法规范给出了以下条件:
指定单个声明,不带括号或其他装饰。
The condition in an
if
orwhile
statement can be either an expression, or a single variable declaration (with initialisation).Your second and third examples are neither valid expressions, nor valid declarations, since a declaration can't form part of an expression. While it would be useful to be able to write code like your third example, it would require a significant change to the language syntax.
The syntax specification in 6.4/1 gives the following for the condition:
specifying a single declaration, with no parentheses or other adornments.
如果您想将变量包含在更窄的范围内,您可以随时使用附加的
{ }
If you want to enclose variables in a narrower scope, you can always use additional
{ }
最后一部分已经可以工作了,你只需要把它写得稍有不同:
The last section already works, you just have to write it slightly different:
这是一个使用循环的丑陋解决方法(如果两个变量都是整数):
但这会让其他程序员感到困惑,而且代码相当糟糕,因此不推荐。
一个简单的封闭
{}
块(如已经推荐的那样)更容易阅读:Here's an ugly workaround using a loop (if both variables are integers):
But this will confuse other programmers and it's rather bad code, so not recommended.
A simple enclosing
{}
block (as already recommended) is much easier to read:还需要注意的一件事是,较大的 if 块内的表达式
不一定保证以从左到右的方式进行计算。我当时遇到的一个相当微妙的错误与编译器实际上是从右到左而不是从左到右进行测试这一事实有关。
One thing to note, also is that the expressions inside the larger if-block
are not necessarily guaranteed to be evaluated in a left-to-right fashion. One rather subtle bug that I had back in the day had to do with the fact that the compiler was actually testing right-to-left instead of left-to-right.
通过一点模板魔法,您可以解决无法声明多个变量的问题:(
注意,这会丢失短路评估。)
With a little template magic you can kind of sort of get around the problem of not being able to declare multiple variables:
(Note, this looses the short circuit evaluation.)