C++ 很难理解复制构造函数是从哪里来的

C++ 很难理解复制构造函数是从哪里来的,c++,templates,constructor,C++,Templates,Constructor,我有以下小代码: template <typename T> class V { public: T x; explicit V(T & _x) :x(_x){} }; int main() { V<float> b(1.0f); // fails return 0; } 模板 第五类 { 公众: tx; 显式V(T&x) :x(x){} }; int main() { vb(1.0f);//失败 返

我有以下小代码:

template <typename T>
class V
{
    public:
        T x;

    explicit V(T & _x)
    :x(_x){}

};

int main()
{
    V<float> b(1.0f); // fails
    return 0;
}
模板
第五类
{
公众:
tx;
显式V(T&x)
:x(x){}
};
int main()
{
vb(1.0f);//失败
返回0;
}
而它恰好失败了。g++4.4.5返回的消息是:

g++-O0-g3-Wall-c-fmessage length=0-MMD-MP-MF“main.d”-MT“main.d”-o“main.o”“../main.cpp”

。/main.cpp:在函数“int main()”中:

。/main.cpp:19:错误:对“V::V(float)”的调用没有匹配的函数

。/main.cpp:10:注:候选项为:V::V(T&)[带T=float]

。/main.cpp:6:注意:V::V(const V&)


问题是。。。第二个构造器是从哪里来的?我真的不知道……

其他答案讨论了为什么会出现编译时失败(这是大多数问题的主题,当这些失败是问题中最突出的部分时)。然而。关于你明确的问题,“第二个构造函数是从哪里来的?”

12.8/4标准的“复制类对象”规定:

如果类定义没有显式声明副本构造函数,则隐式声明副本构造函数


如果希望避免使用隐式复制构造函数,可以使用几个“不可复制”的习惯用法之一(例如
boost::noncopyable
):

编译器为类提供了复制构造函数和赋值运算符。它试图将该复制构造函数与您在
main
中的语句匹配。此代码的问题在于,在类
V
的构造函数中,您将参数作为非常量引用。当您执行
vb(1.0f)
时,编译器将为值
1.0f
创建一个类型为
float
的未命名临时变量。但是,此未命名的临时对象不能绑定到非常量引用,它只能绑定到常量引用。因此,您需要将构造函数签名更改为显式V(const T&x)

这一点。编译器会帮你做这件事。提供了默认构造函数和副本构造函数。哦,我应该看到。。。。非常感谢!让我分心的是,复制构造函数根本不适用于我得到失败的表达式,因为无法从float literal(V(float&)构造函数是显式的)获得V对象。@user这就是GCC说“候选者”的原因。候选者都是建构者,但“可行的候选者”才是真正能够接受论点的人。