Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数中临时调用的构造被解释为声明_C++_Temporary_Most Vexing Parse_Construction - Fatal编程技术网

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.
}
被解释为(如果有标准构造函数)的声明。这是有意义的,而且是完全正确的,因为您可以只使用{}括号使构造显式化。但我不明白的是:

  • 为什么bar0的构造存在问题? 所有
    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
    失败

  • 此外,在构造任何条之前声明x。为什么编译器不对此抱怨

  • 最后一个问题与我的最后一行示例代码有关。长话短说:编译器认为我希望他做什么?我在哪里错过了阴影的出现

    PS:如果感兴趣,我使用gcc-4.9.2。
    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