在if语句的条件部分中定义一个variables?

我只是感到震惊,这是允许的:

if( int* x = new int( 20 ) ) { std::cout << *x << "!\n"; // delete x; } else { std::cout << *x << "!!!\n"; // delete x; } // std:cout << *x; // error - x is not defined in this scope 

那么,这是标准所允许的,还是只是一个编译器扩展?


PS由于有几个意见,请忽略这个例子是“坏”或危险的。 我知道什么 作为一个例子,这只是我想到的第一件事情。

自C ++ 98以来,这是规范所允许的。

从第6.4节“select声明”:

声明中引入的名称(由type-specifier-seq或条件声明者引入)在声明的范围内,直到由条件控制的子语句结束。

以下示例来自同一节:

 if (int x = f()) { int x; // ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x } 

这是标准的,即使在旧的C ++ 98版本的语言中:

在这里输入图像说明

不是一个真正的答案(但评论不太适合代码示例),更多的原因是它非常方便:

 if (int* x = f()) { std::cout << *x << "\n"; } 

每当一个API返回一个“选项”types(也可能有一个布尔转换)时,可以利用这种types的结构,以便该variables只能在使用其值的上下文中访问。 这是一个非常强大的成语。

在一段时间的条件部分定义一个variables, ifswitch语句是标准的。 相关的条款是6.4 [stmt.select]段落1,它定义了条件的语法。

顺便说一句,你的使用是毫无意义的:如果new失败它抛出一个std::bad_allocexception。

下面是一个例子,演示了在if条件中声明的variables的非典型用法。

variables的types是int & ,它既可以转换为布尔值,也可以在thenelse分支中使用。

 #include <string> #include <map> #include <vector> using namespace std; vector<string> names {"john", "john", "jack", "john", "jack"}; names.push_back("bill"); // without this push_back, my g++ generated exe fails :-( map<string, int> ages; int babies = 0; for (const auto & name : names) { if (int & age = ages[name]) { cout << name << " is already " << age++ << " year-old" << endl; } else { cout << name << " was just born as baby #" << ++babies << endl; ++age; } } 

输出是

 john was just born as baby #1 john is already 1 year-old jack was just born as baby #2 john is already 2 year-old jack is already 1 year-old bill was just born as baby #3 

不幸的是,条件中的variables只能用'='声明语法来声明。

这排除了具有显式构造函数的其他可能有用的types的情况。

例如,使用std::ifstream下一个示例将不会编译…

 if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile! std::cout << "true: " << is.rdbuf(); } else { is.open("c:/tmp/input2.txt"); std::cout << "false: " << is.rdbuf(); }