C++ 函数中临时调用的构造被解释为声明
最近我遇到了一个问题,这个问题在某种程度上(但只是在某种程度上)对我来说是有意义的。它基于将临时构造函数的构造解释为单个(!)构造函数参数的声明。请看下面的最小示例C++ 函数中临时调用的构造被解释为声明,c++,temporary,most-vexing-parse,construction,C++,Temporary,Most Vexing Parse,Construction,最近我遇到了一个问题,这个问题在某种程度上(但只是在某种程度上)对我来说是有意义的。它基于将临时构造函数的构造解释为单个(!)构造函数参数的声明。请看下面的最小示例 #include <iostream> class Foo0{ public: Foo0(int a){}; void doStuff() {std::cout<<"maap"<<std::endl;}; }; class Foo1{ public: Foo1(int a){};
#include <iostream>
class Foo0{
public:
Foo0(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo1{
public:
Foo1(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo2{
public:
Foo2(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Bar{
public:
Bar(Foo0 foo0, Foo1 foo1, Foo2 foo2){};
};
int main () {
int x = 1;
Bar bar0(Foo0(x), Foo1(x), Foo2(x)); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’; conflicting declaration ‘Foo2 x’ previous declaration as ‘Foo0 x’
Bar bar1(Foo0{x}, Foo1(x), Foo2(x)); // Works WTF
Bar bar2(Foo0(x), Foo1{x}, Foo2(x)); // Works WTF
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
Bar bar4(Foo0{x}, Foo1{x}, Foo2{x}); // Works totally makes sens to me
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious though.
}
被解释为(如果有标准构造函数)的声明。这是有意义的,而且是完全正确的,因为您可以只使用{}括号使构造显式化。但我不明白的是:
Foo
s没有标准构造函数。因此,将类似于Foo0(x)
的内容解释为x
的声明是没有意义的Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
bar1
和bar2
有效?
对我来说,bar4
的构造显然是可行的,因为我对所有临时Foo
s都使用了{}-括号,因此我清楚地知道我想要什么Foo
s中的一个一起使用即可解决问题。。。为什么构建bar3
失败PPS:我对
bar
的构造函数使用了相同的方法,使用了三个Foo0
s作为参数。同样的故事。但是,该错误并没有说明冲突声明,而是说明了对x
1)的重新定义。在本例中,Foo0(x)被视为函数bar0的一个参数。在这里,它是否具有标准构造函数并不重要。它不是局部变量声明和初始化,而是函数声明中的参数声明
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
2) 我猜这和语法分析有关,但如果我错了,有人会纠正我。。示例bar1和bar2可以工作,因为编译器一看到{}的第一次出现就知道bar1和bar2是局部变量声明(而不是函数声明)。这些第一次出现的{}出现在x两次声明为函数参数之前
3) bar3的构造失败,因为编译器首先假定bar3是一个函数声明。函数声明采用三个参数,它们都命名为x。显然,这是不正确的
4) 函数声明中的x只是参数的名称。它的作用域与之前声明的整数x不同。规则是,如果一个声明具有函数声明的语法,那么它就是一个;否则它是一个变量声明。这种令人惊讶的例子有时被称为 这是一个函数声明:
bar0
是名称,Bar
是返回类型,参数类型是Foo0
,Foo1
和Foo2
。参数名称都是x
,这是非法的-函数参数的名称必须不同。如果将x
x
x
更改为x
y
z
错误消失)
这些行并创建类型为Bar
的对象bar1
、bar2
和bar4
。它们不能作为函数声明进行分析,因为{}
符号在函数声明中是无效的语法
因此,Foo0{x}
等是为Bar
的构造函数提供参数的表达式Foo0{x}
和Foo0(x)
是使用初始值设定项x
声明类型为Foo0
的临时值的等效方法
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
我认为这是一个编译器错误;部分Foo2{x}
表示此行不能是函数声明;它看起来像一个变量的有效声明bar3
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious
x
是一个int
;它没有任何方法。正如您所知,bar0
是一个函数的声明,它接受三个Foo
s并返回一个Foo
,它本身不是Foo
对象。另外,bar3
的声明不起作用这一事实在您使用的任何编译器中都是一个bug。该行应该像在中一样工作。@0x499602D2在g++4.8.1中为我安装了错误,只是为了更正:bar0
是一个函数的声明,该函数使用三个Foo
s并返回一个Bar
。bar0是一个合法的函数声明吗?在这种情况下,type(name)
是什么意思?它只是绑定/分组,比如int(*foo)
——那么类型(名称)
与类型名称
相同吗?我真的开始喜欢C++了。@ JasonN的一个很好的解释谢谢。复杂解析的惊人性<代码>-Wvexing parse很有趣。悲伤的同时。
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious