簡體   English   中英

多態unique_ptr復制省略

[英]polymorphic unique_ptr copy elision

我有以下代碼適用於Clang 5.0但不適用於Clang 3.8,啟用了C ++ 14:

class Base {};
class Derived : public Base {};

std::unique_ptr<Base> MakeDerived()
{
    auto derived = std::make_unique<Derived>();
    return derived;
}

int main()
{
    auto base = MakeDerived();
    std::cout << "Type: " << typeid(base).name() << '\n';
}

現場樣本

在這種情況下,由於復制省略,返回值在技術上是移動構造的嗎? 如果是這樣,這是否意味着unique_ptr的移動構造函數旨在支持用戶類類型的隱式向上轉換? cppreference文檔 (#6)中很難說,除非我在該文檔頁面上假設模板類型U與類本身的類型T明顯不同。

顯而易見的一件事就是unique_ptr不是可復制構造的,因為我沒有通過std::move()將它轉換為rvalue,所以沒有其他解釋為什么代碼會編譯而不是復制省音。 但是因為它不適用於接受-std=c++14標志的clang 3.8,我想確保標准本身保證某個地方(如果是這樣,哪里),這只是一個編譯器錯誤或缺乏支持問題在Clang的v3.8中。

復制省略(在C ++ 17之前)總是要求省略的構造函數實際可訪問,因此它不能成為代碼工作的原因。

但請注意,C ++(自C ++ 11以來)有一個規則(12.8 / 32),歸結為以下內容:“在返回對象時,在某些情況下,首先嘗試將對象視為右值,並且僅在失敗了,把它當作左值。“

在C ++ 11中,這些“特定情況”是“復制省略是可能的”,這要求返回的對象和返回類型是相同的類型(模數cv限定)。

在C ++ 14中,這些“特定情況”被放寬為“可以復制省略,或者返回的對象是函數中的局部變量”。

因此,在C ++ 11,代碼失敗,因為std::unique_ptr<Derived> (類型derived )為不同std::unique_ptr<Base> (返回類型),等等std::move將不得不使用。

在C ++ 14中,代碼成功,因為derived是函數中的局部函數,因此首先將其視為rvalue。 這使您引用的構造函數模板適用:

如果U*可以轉換為T*std::unique_ptr<T>可以從std::unique_ptr<U>類型的右值構造。

您的Clang 3.8似乎表現出C ++ 11的行為; 或許它(尚未完全)在該版本中實現了C ++ 14的輕松方面。


(是的,確實你應該假設“模板類型” U與類的模板參數T 。這就是它首先被引入的原因:#6描述的構造函數是構造函數模板 )。

return調用unique_ptr的轉換移動構造函數模板, template<class U, class E> unique_ptr(unique_ptr<U, E>&&) 沒有任何缺點; 它取決於核心問題1579解決方案對derived的隱含移動。

暫無
暫無

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

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