C ++,'if'expression式中的variables声明

这里发生了什么?

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节阐述了如何在select语句条件中声明的variables的范围延伸到由条件控制的子语句的末尾。 但是,我不知道在什么地方不能在括号里面加括号,也没有在每个条件下只说一个声明。

即使在只需要一个声明的情况下,这个限制也是令人讨厌的。 考虑这个。

 bool a = false, b = true; if(bool x = a || b) { } 

如果我想input“if”-body作用域,并将x设置为false,则声明需要括号(因为赋值运算符的优先级低于逻辑或),但由于不能使用括号,因此需要在外部声明x显然这个例子是微不足道的,但更实际的情况是a和b是返回需要testing的值的函数

那么,我想做的是不符合标准,还是我的编译器只是把我的球(VS2008)?

ifwhile语句中的条件可以是expression式 ,也可以是单个variables声明 (带有初始化)。

你的第二个和第三个例子既不是有效的expression式,也不是有效的声明,因为声明不能构成expression式的一部分。 虽然能够像第三个例子一样编写代码会很有用,但是需要对语言语法进行重大改变。

我不知道在什么地方不能在括号里面加括号,也没有在每个条件下只说一个声明。

6.4 / 1中的语法规范给出了以下条件:

 condition: expression type-specifier-seq declarator = assignment-expression 

指定一个单一的声明,没有括号或其他装饰。

我想你已经暗示了这个问题。 编译器应该用这个代码做什么?

 if (!((1 == 0) && (bool a = false))) { // what is "a" initialized to? 

“&&”运算符是一个短路逻辑AND。 这意味着如果第一部分(1==0)结果是错误的,那么应该不对第二部分(bool a = false)进行评估,因为已经知道最终答案是错误的。 如果(bool a = false)不被评估,那么稍后如何处理代码呢? 我们只是不初始化variables,并保持它不确定? 我们将它初始化为默认值? 如果数据types是一个类,并且这样做有不良副作用? 如果不是bool而是使用了一个类,而且它没有默认的构造函数,那么用户必须提供参数 – 那么我们该怎么做呢?

这是另一个例子:

 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? 

看起来像你发现的限制似乎是完全合理的 – 它防止了这种歧义的发生。

如果要将variables放在更窄的范围内,则可以随时使用附加的{ }

 //just use { and } { bool a = false, b = true; if(bool x = a || b) { //... } }//a and b are out of scope 

最后一节已经有效了,你只需要写一点不同的东西:

 if (int a = Func1()) { if (int b = Func2()) { // do stuff with a and b } } 

从C ++ 17开始,你试图做的事情终于可能了 :

 if (int a = Func1(), b = Func2(); a && b) { // Do stuff with a and b. } 

注意使用; 而不是分开声明和实际情况。

这是一个丑陋的解决方法,使用循环(如果两个variables都是整数):

 #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; } 

但是这会混淆其他程序员,而且代码太差,所以不推荐。

一个简单的封闭{}块(如已经推荐的)更容易阅读:

 { int a = func1(); int b = func2(); if (a && b) { std::cout << "a = " << a << std::endl; std::cout << "b = " << b << std::endl; } } 

有一件事要注意,也是在较大的if块内的expression式

 if (!((1 == 0) && (bool a = false))) 

不一定保证以从左到右的方式进行评估。 编译器实际上是从右到左testing,而不是从左到右testing,这是我在当天回来的一个非常微妙的错误。

用一个小小的模板魔法,你可以解决不能声明多个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; } 

(注意,这会影响短路评估。)