簡體   English   中英

為什么刪除模板復制構造函數會導致賦值運算符失靈?

[英]Why delete of templete copy constructor cause assignment operator disfunctional?

我有如下代碼,看起來有點令人困惑。 我定義了一個模板 class。 它有一個用戶定義的構造函數。 當我通過“operator =”聲明此模板 class 的兩個對象時,它的用戶定義構造函數被調用,令我驚訝。 此外,刪除其復制構造函數后,甚至在解析“operator =”期間編譯也無法通過。 模板構造函數的規則是否與非模板 class 不同?

#include "iostream"
using namespace std;

template <typename T>
class MyPtr
{
private:
    T p_;
public:
    MyPtr(T P = NULL): p_(P)
    {
        cout<<"track!!"<<endl;
    }

    //MyPtr(const MyPtr<T> & P) = delete;
    ~MyPtr()
    {
 
    }
};

int main()
{
    int i=3;
    int j=4;
    MyPtr<int> p = i;
    MyPtr<int> pp = j;
}

模板構造函數的規則是否與非模板 class 不同?

不。

MyPtr<int> p = i; (和MyPtr<int> pp = j; )是 復制初始化 請注意,這是初始化而不是賦值,因為效果p由構造函數MyPtr::MyPtr(T)初始化。 例如

MyPtr<int> p = i; // initialization; constructors get called
p = j;            // assignment; assignment operators (operator=) get called

在 C++17 之前, i會先通過MyPtr::MyPtr(T)轉換為MyPtr<int> ,然后將轉換結果,即臨時MyPtr<int>復制/移動以初始化p 即使允許優化復制/移動操作,也需要可訪問復制/移動構造函數。 將復制構造函數聲明為delete會使復制構造函數不可用並且不會生成移動構造函數,從而使MyPtr<int> p = i; 格式不正確,直到 C++17。

由於 C++17 優化是強制性的,並且復制/移動構造函數不需要再次訪問,這意味着您的代碼可以在 C++17 模式下正常編譯,即使將復制構造函數聲明為delete

  • 如果 T 是 class 類型,並且 other 的類型的 cv-unqualified 版本不是 T 或派生自 T,或者如果 T 是非類類型,但 other 的類型是 class 類型,用戶定義的轉換序列檢查可以從 other 的類型轉換為 T 的類型(或者如果 T 是 class 類型並且轉換 function 可用,則轉換為從 T 派生的類型)進行檢查,並通過重載決議選擇最佳的。 如果使用了轉換構造函數,則轉換結果是一個prvalue temporary (until C++17) prvalue expression (since C++17) ,然后用於直接初始化object。 The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

暫無
暫無

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

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