簡體   English   中英

由value傳遞的c ++ copy構造參數

[英]c++ copy construct parameter passed by value

我希望freeFunct在它自己的對象副本a上做非const的東西。

假設freeFunct需要是一個自由函數,因為在實際代碼中它需要許多不同的參數,從所有這些函數調用幾個公共函數,並且沒有必要使它成為任何類的非靜態成員函數。

我想到了三種不同的宣告方式。

我覺得第三種解決方案更糟糕。

前兩個有什么區別嗎?

還有更好的東西嗎?

void freeFunct1(A a){
    a.doStuff(); 
}

void freeFunct2(const A& a){
    A b = a; 
    b.doStuff(); 
}

/**users of freeFunct3 are expected 
 *to give a copy of their variable: 
 *{
 *    A b = a; 
 *    freeFunct3(b); 
 *}
 */
void freeFunct3(A& a){
    a.doStuff(); 
}

第一個是最好的:它允許調用者選擇是復制還是移動他的對象,因此如果調用者不需要保留副本,則可以更有效。

freeFunct1(a);             // "a" is copied and not changed
freeFunct1(std::move(a));  // "a" is moved and perhaps changed

第二個類似,但強制副本。

正如你所說,第三個更容易出錯,因為調用者必須知道它會修改參數。

首先, freeFunct3如果自由函數的語義只是修改其“自己的”對象,則不要執行freeFunct3

其次, freeFunct1freeFunct2之間存在差異,這與移動優化 [C ++ 11], 異常安全和可能的代碼大小有關

使用freeFunct2 (通過引用到const):

  1. 它總是構造一個新的參數副本,永遠不會移動它[C ++ 11]。
  2. 如果A的復制結構拋出異常,它將拋出函數體內
  3. 如果A的復制構造函數是內聯的(函數不是),它將在函數體內展開一次 (即使從多個不同的地方調用函數)。

使用freeFunct1 (按值計算):

  1. [C ++ 11]如果A有一個移動構造函數並且你傳遞一個rvalue(例如調用freeFunct1(A(args)) ),你可以避免復制。
  2. 如果副本(或移動)建設A拋出異常,就會拋出在調用點
  3. 如果A的復制(或移動)構造函數被內聯,它將在每個調用站點多次展開。

或者,您可以重載lvalue / rvalue引用以避免不必要地復制rvalues:

void freeFunct4(const A& a){
    A b = a; 
    b.doStuff(); 
}
void freeFunct4(A&& a){
    a.doStuff(); 
}

IMO,第一個是最好的,最后一個是最差的。

然而,相當多的人已經習慣於通過const引用傳遞他們將默認寫入#2,即使在這種情況下他們需要它試圖避免的副本。

第一個只更改本地副本。 第二個與第一個相同,但有額外的代碼。 第三個將更改a到主叫方可見freeFunct3因為它是一個非const引用。 如果在函數上面的注釋中調用,那么它與第二個版本沒有什么不同。

因此,如果您只想修改本地副本,而不將這些更改傳遞給調用者,那么第一個版本就是我推薦的。

暫無
暫無

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

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