在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, if
和switch
语句是标准的。 相关的条款是6.4 [stmt.select]段落1,它定义了条件的语法。
顺便说一句,你的使用是毫无意义的:如果new
失败它抛出一个std::bad_alloc
exception。
下面是一个例子,演示了在if条件中声明的variables的非典型用法。
variables的types是int &
,它既可以转换为布尔值,也可以在then和else分支中使用。
#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(); }