簡體   English   中英

如何執行復制省略,為什么它不適用於刪除的復制構造函數?

[英]How to enforce copy elision, why it won't work with deleted copy constructor?

我上課不好。 復制此文件將有問題。 我想保證它永遠不會被復制,所以我將其復制構造函數deleted

class A {
  public:
    A();
    A(const A&) = delete;
};

A fun() {
  return A();
};

int main() {
  A a = fun();
};

不幸的是,g ++不會基於以下原因進行編譯:

t.cc: In function ‘A fun()’:
t.cc:8:12: error: use of deleted function ‘A::A(const A&)’
   return A();
            ^
t.cc:4:5: note: declared here
     A(const A&) = delete;
     ^
t.cc: In function ‘int main()’:
t.cc:12:13: error: use of deleted function ‘A::A(const A&)’
   A a = fun();
             ^
t.cc:4:5: note: declared here
     A(const A&) = delete;
     ^

但這是一個非常明顯的情況,應使用復制省略,因此不應調用復制構造函數。 為什么會這樣呢?

直到C ++ 17復制省略是一種優化,編譯器才不需要執行,因此類必須是可復制的,因為編譯器可能要復制(即使實際上不是)。 在C ++ 17中,在許多情況下都可以保證復制省略,然后類將不需要復制ctor。

也可以看看:

http://en.cppreference.com/w/cpp/language/copy_elision

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/ (有關“保證復制省略”的內容)

您也許可以使用在類中聲明復制構造函數的舊技巧,但實際上並未實現它? 只要編譯器實際上不調用復制ctor,就應該滿意。 我沒有對此進行測試,但是我相信它應該在C ++ 17到來之前適用於您的情況。

您無法強制進行復制省略(請參閱其他答案)。

但是,您可以為您的類提供默認的move構造函數,如果無法使用RVO / NRVO,它將移動(因此,不復制)返回值。 為此,您應該為您的move構造函數添加= default

class A {
  public:
    A() = default;
    A(const A&) = delete;
    A(A&&) = default;
    A& operator=(A&&) = default;
};

返回值優化(RVO和NRVO)並不意味着必須放棄可復制或可移動類型所涉及的類型。 無論是否獲得RVO,此要求均適用。

造成這種情況的最可能原因是沒有(當前)強制執行復制刪除。 這是可能發生的優化,並且基於是否在特定實現中應用了該優化,對代碼進行編譯或編譯都沒有意義。

在C ++ 17中,在某些情況下將強制執行RVO,並且將降低可復制性和可移動性的要求。

暫無
暫無

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

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