为什么在“for-loop”中声明变量的“构造函数方式”允许但在“if-statement”中不允许?

时间:2012-09-29 21:32:16

标签: c++ if-statement for-loop language-lawyer

  

可能重复:
  Why can't variables defined in a conditional be constructed with arguments?

考虑这个简单的例子:

/*1*/ int main() {
/*2*/   for (int i(7); i;){break;} 
/*3*/   if (int i(7)) {}
/*4*/ }

为什么第2行编译得很好,而第3行则给出错误?这对我来说有点奇怪,为什么if语句在这方面的处理比for-loop更差?

如果这是特定于编译器的 - 我使用gcc-4.5.1进行了测试:

  

prog.cpp:在函数'int main()'中:   prog.cpp:3:7:错误:在'int'之前预期的primary-expression   prog.cpp:3:7:错误:预期')'在'int'之前

我受到question

的启发

[UPDATE]

我知道这个编译得很好:

/*1*/ int main() {
/*2*/   for (int i = 7; i;){break;} 
/*3*/   if (int i = 7) {}
/*4*/ }

[UPDATE2]

这似乎是纯粹的学术问题 - 但这对于std::unique_ptr<>等无法复制的类型非常重要:

#include <memory>
int main() {
  if (std::unique_ptr<int> i = new (std::nothrow) int(7)) {
  }
  if (std::unique_ptr<int> i(new (std::nothrow) int(7))) {
  }
}

这两种都不允许。不确定新的C ++ 11语法{}

2 个答案:

答案 0 :(得分:11)

C ++标准没有提供基本原理,但我怀疑使用构造函数表示法可能会导致一些不一致。例如,由于if语句中不允许函数声明,因此最令人烦恼的解析实际上意味着预期的内容。例如:

int f();        // function declaration (simple form or the most vexing parse)
if (int f()) {  // illegal in C++ but, when allowed, would be a zero-initialized int
}

在C ++ 2011中,您可以使用大括号初始化:

if (int x{f()}) {
    ...
}

不幸的是,大括号初始化并不总是意味着使用构造函数表示法(我认为它叫做 direct-initialization )。

关于更新:您可以使用以下方法之一:

if (std::unique_ptr<int> p = std::unique_ptr<int>(new int(1))) { ... }
if (auto p = std::unique_ptr<int>(new int(2))) { ... }
if (std::unique_ptr<int>{new int(3)}) { ... }

似乎有很多选择: - )

答案 1 :(得分:2)

就语法而言,原因很简单。

for语句的第一个元素是语句。语句可以创建变量并初始化它们。 if条件是条件。规范确定条件可以创建变量,但只能通过=初始化。

很高兴规范甚至允许你在if中创建变量。它必须有特殊的语法,甚至允许(“条件”不同于“表达式”),这可能是从C继承的东西。

话虽这么说,C ++ 11确实将一个条件定义为能够使用 braced-init-list (spec-speak for“initializer list”)初始化声明。所以它应该是合法的。但由于VS2012尚不支持初始化程序列表......