簡體   English   中英

為什么編譯器在分配時調用模板化副本構造函數?

[英]Why does the compiler invoke a templated copy constructor when assigning?

考慮下面的代碼:

#include <iostream>

template<class T>
struct X
{
    X() = default;

    template<class U>
    X(const X<U>&)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

/*
    template<class U>
    X& operator=(const X<U>&)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        return *this;
    }
*/

};

int main()
{
    X<int> a;
    X<double> b;

    b = a;
}

住在科利魯

如您所見,賦值運算符已被注釋掉。 但是,線

b = a;

編譯良好。 我認為它不應該編譯,因為ab具有不同的類型,並且編譯器默認生成的operator=(const X&)將由基礎類型實例化,因此不會分配X<int>X<double>

令我驚訝的是,代碼已編譯,並且似乎正在調用模板化副本構造函數。 為什么是這樣? 難道是因為編譯器會先嘗試在投ab然后調用默認生成的B::operator=

如果TU是不同的類型,則template<class U> X(const X<U>&)不是復制構造函數,因為它的參數是不同類型的。 換句話說, X<int>X<double>是不相關的類型,因此此構造函數只是它們之間的用戶定義轉換。

請注意,此代碼不會打印任何內容:

X<int> a;
X<int> b { a };

因為在這種情況下,將調用形式為X<int>::X(const X<int>&)的隱式聲明的副本構造X<int>::X(const X<int>&)

編譯器正在生成對X<double>(const X<int>&)的調用,以將X<int>轉換為X<double> 然后調用生成的賦值運算符X<double>& X<double>::operator =(const X<double>&); 做作業。

如果您明確列出所有步驟,它將是:

b.operator =(X<double>(a));

template<class U> X(const X<U>&)是一種通用的用戶定義轉換-請參閱Anton Savin的答案。

隱式類型轉換的規則非常復雜,因此您應警惕用戶定義的轉換函數(“ 更有效的C ++項目5” )。 模板功能更是如此。

編碼

#include <iostream>

template<class T>
struct X
{
    X() = default;

    template<class U>
    X(const X<U>&)
    {
        std::cout << "generalized ctor: " << __PRETTY_FUNCTION__ << std::endl;
    }

/*
    template<class U>
    X& operator=(const X<U>&)
    {
        std::cout << "generalized assignment: " << __PRETTY_FUNCTION__ << std::endl;
        return *this;
    }
*/
};

int main()
{
    X<int> a;
    X<double> b;

    b = a;
}

回報

廣義ctor:X :: X(const X&)[with U = int; T =兩倍]

但是對於operator=未注釋掉),它將返回

廣義賦值:X&X :: operator =(const X&)[with U = int; T = double]。

因此,您正確的是,隱式生成的operator=(const X&)將由基礎類型實例化,並且不會將X<int>分配給X<double> 正如Scott Meyers(請參閱上面的參考資料)所述,您的編譯器面臨着對X<double> b.operator=的調用,該調用采用了const X<double> ,並且發現不存在這樣的函數。 因此,您的編譯器然后嘗試找到可接受的隱式類型轉換序列,該序列可用於使調用成功, 請參閱cpp參考中的規則 您的編譯器會找到通用的用戶定義轉換,並將X<int>轉換為X<double>以具有b.operator=的正確參數類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM