15

可能重复:
为什么不能用参数构造条件中定义的变量?

考虑这个简单的例子:

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

为什么第 2 行编译得很好,而第 3 行给出了错误?这对我来说有点奇怪,为什么 if 语句在这方面比 for 循环更糟糕?

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

prog.cpp:在函数'int main()'中:prog.cpp:3:7:错误:'int'之前的预期主表达式 prog.cpp:3:7:错误:'int'之前的预期')'

我被这个问题启发了

[更新]

我知道这编译得很好:

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

[更新2]

这似乎是纯粹的学术问题 - 但这对于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 语法{}

4

2 回答 2

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()}) {
    ...
}

不幸的是,大括号初始化并不总是与使用构造函数表示法相同(我认为它被称为直接初始化)。

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

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)}) { ... }

似乎有很多选择:-)

于 2012-09-29T21:41:16.080 回答
2

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

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

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

话虽如此,C++11 确实将条件定义为能够使用花括号初始化列表(规范说“初始化程序列表”)来初始化声明。所以应该是合法的。但是由于 VS2012 还不支持初始化列表...

于 2012-09-29T22:14:27.453 回答