最近,当我的类具有只接受一个参数的模板构造函数时,我遇到了一种奇怪的行为。在某些情况下,该课程根本无法初始化。
#include <iostream>
struct Foo
{
template<typename T>
Foo(const T& x)
{
std::cout << "--" << x << std::endl;
}
};
int main(int, char**)
{
Foo f(std::string());
std::cout << "++" << f << std::endl;
return 0;
}
我所拥有的是具有您看到的构造函数的Foo结构。在main中,我创建了一个带有空std :: string的新Foo实例。示例编译,输出为:
++1
WTF ???您可能已经注意到这有三个问题。首先,构造函数从未被调用,其次f被打印为“1”,第三,没有重载的运算符&lt;&lt;使用cout打印Foo,尽管编译器从不抱怨。这意味着f不是一种Foo。
我稍微改变了一下这个例子:
int main(int, char**)
{
Foo f(std::string(""));
std::cout << "++" << f << std::endl;
return 0;
}
...并且编译器抛出一个错误,即没有重载的运算符&lt;&lt;这是正常的。
int main(int, char**)
{
Foo f(std::string("Hello"));
return 0;
}
现在输出是:
--Hello
再次正常。
问题是当向Foo :: Foo传递空对象时,无论是std :: string()还是float()或any_type()。我在GCC 4.4和4.6中测试了这个例子,我发现这种行为非常意外。
你有什么看法?这是一个GCC错误还是我错过了什么?答案 0 :(得分:5)
Foo f(std::string());
它似乎没有像你想象的那样创建Foo
类型的实例。
相反,它声明了一个名为f
的函数,其返回类型为Foo
,参数类型为函数类型(不带参数并返回std::string
)。
与:
相同Foo f(std::string (*)()); //same as yours
这和你的函数声明的唯一区别在于你的情况下参数类型是函数类型(最终衰变为函数指针类型无论如何),在我的例子中,参数类型是函数指针类型(它不需要衰减成指针类型)。
至于它打印++1
的原因是因为它调用operator<<
并将void*
作为参数,并且此函数打印函数的地址。
现在,如果你想声明一个对象,那么你需要使用额外的parens:
Foo f((std::string())); //notice the extra parens!
这声明了一个对象,并调用构造函数:http://ideone.com/Px815
另见本主题:
答案 1 :(得分:2)