为什么输出是0003212?
#include <iostream>
using namespace std;
template<typename X> class C
{
public:
C() { cout<<"0";}
template<class T> C(const C<T>& c) { cout<<"1";}
C(const C<int>& c) { cout<<"2";}
template<class T> C(const C<T*>& c) { cout<<"3";}
};
int main(int argc, char* args[])
{
C<int> c1; // 0
C<double> c2; // 0
C<int*> c3; // 0
C<int> c4(c3); // 3
C<int> c5(c1); // 2
C<int> c6(c2); // 1
C<float> c7(c1); // 2
C<double> c8(c2); // ?
std::cin.get();
return 0;
}
在最后一个含义行中调用了什么?
我可以认为它是一些自动创建的ctor 但无法弄清楚哪一个。
答案 0 :(得分:5)
这里有几种C ++语言规则。
模板不能是复制构造函数。 (标准规则12.8p2)
如果第一个参数类型为
X
,constX&
,X&
,则类volatile X&
的非模板构造函数是一个复制构造函数}或const volatile X&
,并且没有其他参数,或者所有其他参数都有默认参数。
如果未定义复制构造函数,编译器将生成默认构造函数(如果可能)。 (标准规则12.8p7)
如果类定义没有显式声明复制构造函数,则会隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;否则,它被定义为默认值(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。因此,对于课程定义
struct X { X(const X&, int); };
隐式声明了复制构造函数。如果用户声明的构造函数稍后定义为
X::X(const X& x, int i =0) { /∗ ... ∗/ }
那么X
的复制构造函数的任何使用都是不正确的,因为它含糊不清;无需诊断。
如果模板和非模板对参数同样匹配,则非模板获胜。 (标准规则13.3.3)规则是一个难以消化的大混乱,我只会展示重要的部分:
[...]一个可行的函数
F1
被定义为比另一个可行的函数F2
更好的函数,如果[...关于参数匹配...的规则],或者,如果不是,F1
是非模板函数,F2
是函数模板特化[...]
从您提供的代码中,只有
C<int>::C(const C<int>&)
是用户定义的复制构造函数,用于打印2
。 X
以外的所有int
都没有定义复制构造函数,因此编译器会创建一个。{/ p>
另见
答案 1 :(得分:4)
它是由编译器为您生成的复制构造函数,因为它在最后一种情况下最佳匹配。
答案 2 :(得分:0)
在最后一种情况下,您调用默认的复制构造函数。