为什么匿名对象有时需要默认构造函数?

jxh*_*jxh 3 c++ most-vexing-parse

如果我编写以下程序,它可以正常工作:

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

int main () { Foo("hello, world"); }
Run Code Online (Sandbox Code Playgroud)

但是,如果我编写一个稍微不同的程序,我会收到编译错误:

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

std::string x("hello, world");

int main () { Foo(x); }
Run Code Online (Sandbox Code Playgroud)

错误是:

prog.cc: In function 'int main()':
prog.cc:10:20: error: no matching function for call to 'Foo::Foo()'

在IDEONE上可以看到完整的错误.

为什么第二个程序出错而不是第一个出错?

Bry*_*hen 12

您已x使用类型声明了变量Foo

struct Foo {
    Foo(){}
    Foo (std::string x) { std::cout << x << std::endl; }
    void test(){ std::cout << "test" << std::endl; };
};

std::string x("hello, world");

int main () { Foo(x); x.test(); }
Run Code Online (Sandbox Code Playgroud)

打印"测试"


你想要的是使用统一初始化语法 Foo{x}

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

std::string x("hello, world");

int main () { Foo{x}; }
Run Code Online (Sandbox Code Playgroud)

打印"你好,世界"

  • @jxh你对它有什么期望?`a`用`"a"初始化``什么?同样的原因,你可以有`int a(1),2;`,你需要为第二个对象命名. (2认同)

M.M*_*M.M 8

Foo(x);意思是一样的Foo x;.您可以将冗余括号添加到变量的名称中.

所以你需要默认的构造函数,因为这是创建一个x没有参数传递给构造函数的变量.

您可以通过Foo{x};在C++ 11中执行此操作来解决此问题.

解析规则是,如果某些东西可能是有效的声明和有效的非声明语句,那么它实际上是一个声明.另见最烦恼的解析

  • @MattMcNabb,使用单个括号适用于两个:)我认为当你知道要注意什么时,大括号初始化是很好的. (2认同)