2017-09-14 159 views
4

考虑这个非常简单的代码:C++函数定义和变量声明不匹配?

#include <memory> 

class Foo 
{ 
public: 
    Foo() {}; 
}; 

class Bar 
{ 
public: 
    Bar(const std::shared_ptr<Foo>& foo) {} 
}; 

int main() 
{ 
    Foo* foo = new Foo; 
    Bar bar(std::shared_ptr<Foo>(foo)); 
    return 0; 
} 

为什么Visual Studio的报告

warning C4930: 'Bar bar(std::shared_ptr<Foo>)': prototyped function not called (was a variable definition intended?) 

并没有创造......这怎么行Bar bar(std::shared_ptr<Foo>(foo));被解释为一个函数的定义没有bar对象?

我检查Do the parentheses after the type name make a difference with new?C++: warning: C4930: prototyped function not called (was a variable definition intended?),但我觉得我的问题是不同的这里,因为我没有使用语法Foo()也不Bar()

编辑:请注意,它成功编译:

Foo* foo = new Foo; 
std::shared_ptr<Foo> fooPtr(foo); 
Bar bar(fooPtr); 
+9

C++最令人烦恼的解析。 –

+0

@眠りネロクno,gcc编译它 –

+1

@RichardHodges所以MSVC,它只是一个警告。眠りネロク是正确的。 – Quentin

回答

14

这个问题是关于C++'s most vexing parse。声明:

Bar bar(std::shared_ptr<Foo>(foo)); 

声明了一个名为bar返回Bar,并采取所谓std::shared_ptr<Foo>类型的foo参数的功能。

最里面的括号不起作用。这是因为如果你写了下面的:

Bar bar(std::shared_ptr<Foo> foo); 

假设C++ 11(因为你已经在使用std::shared_ptr),你可以使用支具语法代替括号

Bar bar(std::shared_ptr<Foo>{foo}); 

这实际上会构造一个Bar类型的对象bar,因为上面的语句不能被解释为声明,因为的大括号。

+3

你的意思是它相当于'Bar bar(std :: shared_ptr foo);'? – jpo38

+2

正确,但如果您有关于最烦人的解析的解释或链接并提供解决方案,可能会更好。 – aschepler

+0

可能的C++ 98或TR1解决方案是在预期的变量名后使用双括号。正如您所指出的那样,参数名称可以包含在免费括号中,但不包括整个参数列表,即使它只包含一个参数声明。所以,例如:''酒吧((std :: tr1 :: shared_ptr (foo))''。虽然不太可读 –