为什么不使用我的(模板)构造函数进行此初始化?

Why isn't this initialization using my (template) constructor?

本文关键字:初始化 构造函数 我的 模板 为什么不      更新时间:2023-10-16

为什么输出是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但不知道是哪一个。

这里有几个C++语言规则。

  1. 模板不能是复制构造函数。(标准规则12.8p2)

    如果类X非模板构造函数的第一个参数类型为X&、常量X&volatile X&const volatile X&,并且没有其他参数,或者所有其他参数都有默认参数,则该构造函数是复制构造函数。

  2. 如果没有定义复制构造函数,编译器会生成一个默认的复制构造函数(如果可能的话)。(标准规则12.8p7)

    如果类定义没有显式声明复制构造函数,则隐式声明一个如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;否则,它被定义为默认值(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不赞成使用后一种情况。因此,对于类别定义

    struct X {
    X(const X&, int);
    };
    

    复制构造函数是隐式声明的。如果用户声明的构造函数后来被定义为X::X(const X& x, int i =0) { /∗ ... ∗/ }那么CCD_ 7的复制构造函数的任何使用都是由于歧义而形成的;不需要进行诊断。

  3. 如果一个模板和非模板的参数匹配得同样好,则非模板获胜。(标准规则13.3.3)该规则是一个难以消化的大混乱,我只展示重要部分:

    […]如果[…rules about argument matching…],则可行函数F1被定义为比另一个可行函数F2更好的函数,或者,如果不是,则F1是非模板函数,F2是函数模板专用化[…]

根据您提供的代码,只有

C<int>::C(const C<int>&)

是一个用户定义的复制构造函数,用于打印2。除了int之外的所有X都没有定义复制构造函数,因此编译器会创建一个。

另请参见

  • 模板复制构造函数因特定的模板类型而失败以及
  • 初始化忽略构造函数模板

它是编译器为您生成的复制构造函数,由于它是最匹配的,所以在最后一种情况下选择它。

在最后一种情况下,您调用默认的复制构造函数。