为什么将括号与默认构造函数一起使用会导致创建变量?

Why does using parentheses with a default constructor result in creation of the variable?

看完 Louis Brandy 在 CppCon 2017 上的演讲后,我震惊地发现这段代码实际上可以编译:

#include <string>

int main() {

    std::string(foo);

    return 0;
}    

并且出于某种原因 std::string(foo) 它与 std::string foo 相同,即声明一个变量。我发现它绝对违反直觉,并且看不出 C++ 以这种方式工作的任何理由。我希望这会给出有关未定义标识符 foo.

的错误

它实际上使像 token1(token2) 这样的表达式比我之前想象的有更多可能的解释。

所以我的问题是:这种恐怖的原因是什么?什么时候真正需要这条规则?

P.S。抱歉,标题措辞不佳,请随时更改!

因为这个问题被标记了 , the direct answer is that, from [stmt.ambig]:

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

同样,对于函数,在 [dcl.ambig.res]:

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct that could possibly be a declaration a declaration.

因此:

Why oh why is std::string("foo") so different from std::string(foo)

前者不能声明。后者 可以 是一个声明,带有一组多余的括号。因此,前者 不是 声明,而后者 .

潜在的问题是,在语法上,声明符可以以 ( 开头,这可能使其与函数式显式类型转换无法区分。与其想出任意复杂的规则来尝试确定用户的意思,语言只是选择一个,并且用户很容易修复代码以实际执行他的意思。