C++,'if' 表达式中的变量声明
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7836867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++, variable declaration in 'if' expression
提问by Neutrino
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 expains 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.
2003 标准中的第 6.4.3 节解释了在选择语句条件中声明的变量如何具有扩展到由条件控制的子语句末尾的范围。但我没有看到它在哪里说明不能在声明周围加上括号,也没有说明每个条件只有一个声明。
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
如果我想输入 x 设置为 false 的“if”-body 作用域,则声明需要括号(因为赋值运算符的优先级低于逻辑 OR),但由于不能使用括号,因此需要在外部声明 x主体,将该声明泄漏到比预期更大的范围。显然这个例子是微不足道的,但更现实的情况是 a 和 b 是返回需要测试的值的函数
So is what I want to do non-conformant to the standard, or is my compiler just busting my balls (VS2008)?
那么我想做的事情不符合标准,还是我的编译器只是破坏了我的球(VS2008)?
采纳答案by fwyzard
As of C++17 what you were trying to do is finally possible:
从 C++17 开始,您尝试做的事情终于成为可能:
if (int a = Func1(), b = Func2(); a && b)
{
// Do stuff with a and b.
}
Note the use of ;
of instead of ,
to separate the declaration and the actual condition.
注意使用 of;
而不是,
将声明和实际情况分开。
回答by James Johnston
I think you already hinted at the issue. What should the compiler do with this code?
我想你已经暗示了这个问题。编译器应该如何处理这段代码?
if (!((1 == 0) && (bool a = false))) {
// what is "a" initialized to?
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 uses a
? 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 of bool
you used a class and it had no default constructor such that the user mustprovide parameters - what do we do then?
“&&”运算符是一个短路逻辑与。这意味着如果第一部分(1==0)
结果为假,则(bool a = false)
不应评估第二部分,因为已经知道最终答案将是假的。如果(bool a = false)
没有评估,那么稍后使用的代码怎么办a
?我们会不会不初始化变量并让它保持未定义状态?我们会将其初始化为默认值吗?如果数据类型是一个类并且这样做会产生不良副作用怎么办?如果不是bool
您使用了一个类并且它没有默认构造函数以便用户必须提供参数,那我们该怎么办?
Here's another example:
这是另一个例子:
class Test {
public:
// note that no default constructor is provided and user MUST
// provide some value for parameter "p"
Test(int p);
}
if (!((1 == 0) && (Test a = Test(5)))) {
// now what do we do?! what is "a" set to?
Seems like the limitation you have found seems perfectly reasonable - it prevents these kinds of ambiguities from happening.
似乎您发现的限制似乎完全合理 - 它可以防止发生此类歧义。
回答by Mike Seymour
The condition in an if
or while
statement can be either an expression, or a single variable declaration(with initialisation).
if
orwhile
语句中的条件可以是表达式,也可以是单个变量声明(带初始化)。
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.
您的第二个和第三个示例既不是有效的表达式,也不是有效的声明,因为声明不能构成表达式的一部分。虽然能够像第三个示例一样编写代码会很有用,但它需要对语言语法进行重大更改。
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.
我没有看到它在哪里说明不能在声明周围加上括号,也没有说明每个条件只有一个声明。
The syntax specification in 6.4/1 gives the following for the condition:
6.4/1 中的语法规范给出了以下条件:
condition:
expression
type-specifier-seq declarator = assignment-expression
specifying a single declaration, with no parentheses or other adornments.
指定单个声明,没有括号或其他修饰。
回答by crashmstr
If you want to enclose variables in a narrower scope, you can always use additional { }
如果你想在一个更窄的范围内包含变量,你总是可以使用额外的 { }
//just use { and }
{
bool a = false, b = true;
if(bool x = a || b)
{
//...
}
}//a and b are out of scope
回答by Bo Persson
The last section already works, you just have to write it slightly different:
最后一部分已经可以了,你只需要稍微写点不同的:
if (int a = Func1())
{
if (int b = Func2())
{
// do stuff with a and b
}
}
回答by basic6
Here's an ugly workaround using a loop (if both variables are integers):
这是使用循环的丑陋解决方法(如果两个变量都是整数):
#include <iostream>
int func1()
{
return 4;
}
int func2()
{
return 23;
}
int main()
{
for (int a = func1(), b = func2(), i = 0;
i == 0 && a && b; i++)
{
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
}
return 0;
}
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:
一个简单的封闭{}
块(如已经推荐的)更容易阅读:
{
int a = func1();
int b = func2();
if (a && b)
{
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
}
}
回答by DukeBrymin
One thing to note, also is that the expressions inside the larger if-block
需要注意的一件事是,较大的 if 块中的表达式
if (!((1 == 0) && (bool a = false)))
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.
不一定保证以从左到右的方式进行评估。我在当天遇到的一个相当微妙的错误与编译器实际上是从右到左而不是从左到右测试这一事实有关。
回答by BCS
With a little template magic you can kind of sort of get around the problem of not being able to declare multiple variables:
使用一点模板魔法,您可以解决无法声明多个变量的问题:
#include <stdio.h>
template <class LHS, class RHS>
struct And_t {
LHS lhs;
RHS rhs;
operator bool () {
bool b_lhs(lhs);
bool b_rhs(rhs);
return b_lhs && b_rhs;
}
};
template <class LHS, class RHS>
And_t<LHS, RHS> And(const LHS& lhs, const RHS& rhs) { return {lhs, rhs}; }
template <class LHS, class RHS>
struct Or_t {
LHS lhs;
RHS rhs;
operator bool () {
bool b_lhs(lhs);
bool b_rhs(rhs);
return b_lhs || b_rhs;
}
};
template <class LHS, class RHS>
Or_t<LHS, RHS> Or(const LHS& lhs, const RHS& rhs) { return {lhs, rhs}; }
int main() {
if (auto i = And(1, Or(0, 3))) {
printf("%d %d %d\n", i.lhs, i.rhs.lhs, i.rhs.rhs);
}
return 0;
}
(Note, this looses the short circuit evaluation.)
(注意,这会丢失短路评估。)