簡體   English   中英

C ++移動語義與智能指針相關的復制構造函數和賦值運算符

[英]C++ Move Semantics vs Copy Constructor and Assignment Operator in relation to Smart Pointers

我試圖找出何時使用移動語義以及何時使用復制構造函數和賦值運算符作為經驗法則。 您在類中使用的指針類型(如果有的話)似乎受此答案影響,因此我將其包括在內。

沒有指針 -基於答案,如果您有一個帶有基本類型(如int和string)的POD類,則無需編寫自定義移動或復制構造函數和運算符。

unique-ptr-基於答案,當使用移動語義時,unique_ptr比shared_ptr更適合,因為該資源只能有一個unique_ptr。

shared_ptr-同樣,如果使用復制語義,shared_ptr似乎是可行的方法。 該對象可以有多個副本,因此對我而言,擁有一個指向資源的共享指針是有意義的。 但是,unique_ptr通常比shared_ptr更可取,因此,如果可以,請避免使用此選項。

但:

  1. 什么時候應該使用移動語義?
  2. 什么時候應該使用復制語義?
  3. 我應該同時使用兩者嗎?
  4. 我應該不使用任何方法,而依賴默認的復制構造函數和賦值運算符嗎?

顧名思義,當資源必須完全存在一個所有者時,請使用unique_ptr unique_ptr的副本構造函數被禁用,這意味着不可能存在它的兩個實例。 但是,它是可移動的...很好,因為這允許所有權轉移。

顧名思義, shared_ptr表示資源的共享所有權。 但是,這兩個智能指針之間還有另一個區別: unique_ptrDeleter是其類型簽名的一部分,但它不是shared_ptr的類型簽名的一部分。 那是因為shared_ptr使用“類型擦除”來“刪除”刪除器的類型。 還要注意, shared_ptr也可以移動以轉移所有權(例如unique_ptr

什么時候應該使用移動語義?

盡管shared_ptr可以復制,但是在進行所有權轉讓時(而不是創建新引用),您可能希望無論如何移動它們。 您必須對unique_ptr使用移動語義,因為所有權必須是唯一的。

什么時候應該使用復制語義?

對於智能指針,應該使用復制來增加shared_ptr的引用計數。 (如果您不熟悉引用計數的概念,請研究引用計數垃圾收集。)

我應該同時使用兩者嗎?

是。 如上所述, shared_ptr可以被復制和移動。 復制表示增加參考計數,而移動僅表示所有權轉移(參考計數保持不變)。

我應該不使用任何方法,而依賴默認的復制構造函數和賦值運算符嗎?

要制作對象的逐成員副本時。

  1. 什么時候應該使用移動語義?

    我假設您的意思是,“我什么時候應該給我的班級一個移動構造函數?” 答案是,只要這種類型的移動對象有用,並且默認的move構造函數不能正確執行此工作,就可以解決。 當將資源從一個對象轉移到另一個對象有一些好處時,移動很有用。 例如,移動對std::string很有用,因為它允許從臨時對象復制對象,而不必重新分配和復制其內部資源,而只需將資源從一個移動到另一個即可。 許多類型將從中受益。 另一方面,移動對std::unique_ptr很有用,因為這是在不違反其“唯一所有權”的情況下按值傳遞std::unique_ptr的唯一方法。

  2. 什么時候應該使用復制語義?

    再次,我想這是您的意思:“我什么時候應該給我的班級一個復制構造函數?” 每當您需要能夠制作對象的副本時,就會在對象之間復制內部資源,並且默認的副本構造函數無法正確地完成工作。 復制幾乎對任何類型都有用,除了std::unique_ptr這樣的類型必須對內部資源強制執行唯一所有權。

  3. 我應該同時使用兩者嗎?

    您的類大多數時候應該同時提供復制和移動語義。 最常見的類應該是可復制的和可移動的。 可復制提供了按值傳遞對象的標准語義。 可移動允許通過值傳遞臨時對象時獲得的優化。 這是否意味着必須提供副本或移動構造函數取決於默認構造函數是否做適當的事情。

  4. 我應該不使用任何方法,而依賴默認的復制構造函數和賦值運算符嗎?

    默認的copy和move構造函數只是分別復制或移動類的每個成員。 如果此行為適合復制和移動您的班級,那很好。 大多數時候,這應該足夠好。 例如,如果我有一個包含std::string ,則默認的復制構造函數會將字符串復制過來,而默認的move構造函數會將字符串的資源移動到新對象中-兩者都做適當的工作。 如果您的類包含std::unique_ptr ,則復制將根本無法進行,並且您的類只能移動。 那可能就是您想要的,或者您可能想要實現執行資源的深層副本的副本構造函數。 您應該實現復制/移動構造函數的最重要情況是您的類本身執行資源管理時(例如,使用newdelete )。 如果是這樣的話,默認的構造函數幾乎永遠不會在管理這些資源方面做得很好。

這里的所有內容都類似地適用於賦值運算符。

暫無
暫無

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

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