2012-04-12 57 views
4

我正在討論如何正確處理容器參數。我應該清除()容器作爲參數傳入還是交換新對象?

我們有一個函數,它在容器參數,並希望只返回裝滿容器什麼功能付諸它:

class bar; 

void foo(std::vector<bar> &bars) 
{ 
    //do stuff that fills bars. 
    //exceptions may be thrown. 
    //we may also legally return early 
    return; 
} 

在討論的一個方面,我們有人們說我們應該先bars.clear()然後運行該功能。

例如:

void foo(std::vector<bar> &bars) 
{ 
    bars.clear(); 
    //do stuff that fills bars. 
    //exceptions may be thrown. 
    //we may also legally return early 
    return; 
} 

我自己的偏好是試圖儘可能接近我可以達到強異常保證,這意味着建立一個本地容器,灌裝即並在返回之前交換,但在其他方面留下bars不變。

例如:

void foo(std::vector<bar> &bars) 
{ 
    std::vector<bar> localBars; 
    //do stuff that fills localBars. 
    //exceptions may be thrown. 
    //we may also legally return early 
    if (returnEarly) 
    { 
     bars.swap(localBars); 
     return; 
    } 
    //do more stuff that may change localBars 

    bars.swap(localBars); 
    return; 
} 

第一個例子是 '經典' 方法;在做任何事情之前清理你的參數並從那裏開始。

對我來說,第二種方法建立了一個強大的異常保證(假設沒有其他函數可以改變內部狀態),並避免了clear()調用。

挑選一種方法比另一種有什麼優點或缺點?

請注意,對於此功能,強烈的例外保證不是必需的;如果該函數在參數或其他任何內容中沒有任何失敗,那麼在它到達異常處理程序之前,它會起作用。

+0

http://stackoverflow.com/faq:如果你問這個問題的動機是「我想參加關於______的討論」,那麼你不應該在這裏問。 – 2012-04-12 17:06:58

+0

我正在討論...,兩邊的優點和缺點似乎是對我來說完全有效的問題 – Grizzly 2012-04-12 17:08:06

+1

爲什麼不返回結果?那麼這個函數就不會有副作用,這是最強有力的例外保證。 – 2012-04-12 17:09:12

回答

1

這兩者真的不同。的clear

優點:

  • 重用內存在的swapbars

優點離開

  • 沒有過時的信息:

    • 強異常保證

    這個問題不能回答在一般,你尋求什麼語義/保證你的情況

  • +0

    可能是我將要得到的最好的解決方案/總結,比「我們總是這樣做」更好的類型的反應/感覺我在本地獲得,這首先讓我想到這裏。特別是在我的情況下,它將取決於所涉及的功能。我想更好地瞭解每種方法的優點,並確保沒有任何潛伏在我沒有看到的解決方案中的大象。謝謝大家誰迴應(或誰會迴應)。 – Taeolas 2012-04-12 17:58:33

    1

    您已經提到了使用swap的一個優點:它提供了一個強大的異常保證 。這個問題真的很重要嗎? 問題:如果客戶端傳遞的參數將立即被 在異常傳播時破壞(幾乎總是出現在我看到的 代碼中),那真的沒關係。

    還有另外一個重要的區別:clear()不釋放內存或減少容量 。如果客戶端代碼在循環中調用您的函數, 的矢量定義在循環外部,矢量將快速 達到其最大大小,並且在填充 時不會有任何重新分配。隨着交換戰略,當然,你總是重新分配。 如果你不關心這種性能問題,你應該返回向量,而不是將它的非const引用作爲一個參數, 。

    1

    swap()在例外情況下更好。如果容器很大並且你有內存限制,清除可能會有優勢。一個功能更強大/清潔風格可以是:

    std::vector<bar> void foo() 
    { 
        std::vector<bar> bars; 
        ... 
        return bars; 
    } 
    

    RVO會照顧它的大部分時間,並與C++ 11個move構造函數/賦值它只會是有效的。

    +0

    理想情況下,我很想返回酒吧,但目前我正在處理的示例無法處理此時的重構。在未來,這將是我寧願去的路線。 – Taeolas 2012-04-12 17:13:15

    +1

    我幾乎提到了我自己的回報價值的可能性。使用他所具有的接口的常見原因是性能,而關鍵性能問題之一是如果您在呼叫中不斷重複使用相同的矢量,它很快就會獲得足夠的容量,因此不需要新的分配。沒有辦法使用返回值來實現這一點。 – 2012-04-12 17:17:19

    +0

    @詹姆斯,我完全同意你的表現。但在做過早優化時應該小心。我已經看到了太多的「明智的,笨重的」優化,這些優化是在可靠的妥協和項目的長期可維護性的情況下完成的。 「It Depends」 – dpiskyulev 2012-04-12 17:40:46

    相關問題