2012-05-04 57 views
5

如果我使用auto_ptr作爲填充大向量的函數的返回值,則會使該函數成爲源函數(它將創建內部auto_ptr並在返回非const auto_ptr)。但是,我不能在STL算法中使用這個函數,因爲爲了訪問數據,我需要對auto_ptr進行解引用。我猜想一個很好的例子是一個大小爲N的矢量場,每個矢量有100個分量。如果N很大,那麼函數返回的每個100分量矢量的值或ref都不相同。針對大型向量的返回值優化vs auto_ptr

此外,當我嘗試這個非常基本的代碼:

class t 
{ 
    public: 
     t() { std::cout << "ctor" << std::endl; } 
     ~t() { std::cout << "dtor" << std::endl; } 
}; 

t valueFun() 
{ 
    return t(); 
} 

std::auto_ptr<t> autoFun() 
{ 
    return std::auto_ptr(new t()); 
} 

兩個autoFun和樂趣調用導致與輸出

男星 析構函數

,所以我不能真正看到自動變量,正在被創建以轉移到返回聲明。這是否意味着爲ValueFun調用設置了返回值優化?在這種情況下,valueFun是否創建了兩個自動對象?

那麼如何優化具有函數的這種大型數據結構的總體?

+0

您是否問RVO是否也適用於您的大型矢量?如果是這樣,你不能只用上面的例子來測試它嗎? – juanchopanza

+0

當我測試它時,是否意味着它適用於所有編譯器/平臺?我應該如何知道RVO是否包含在內,我應該閱讀編譯器規範嗎?如果代碼在具有不同編譯器的HPC羣集上編譯並且庫很大,會發生什麼情況? – tmaric

+0

是的,我明白你的觀點。這是允許編譯器的事情之一,但不是必需的,所以你永遠無法確定。順便說一句你有C++ 11支持嗎? – juanchopanza

回答

4

有許多選項和動態分配可能不是最好的。


在我們深入討論之前:這是一個瓶頸嗎?

如果你沒有配置文件,並確保它是一個瓶頸,那麼這個討論可能完全關閉......記住比分析調試版本幾乎沒有用處。


現在,在C++ 03有多種選擇,從最可口的至少一個:

  • 信任編譯:無名變量即使是在調試使用RVO建立在海灣合作委員會,爲例。
  • 使用「out」參數(按引用傳遞)
  • 在堆上分配,並返回一個指針(聰明與否)
  • 檢查編譯器輸出

個人而言,我相信我的編譯器除非一個分析器證明我錯了。

在C++ 11中,移動語義幫助我們獲得更多信心,因爲每當有一個return語句時,如果RVO無法啓動,則可以自動使用移動構造函數(如果可用);並移動構造函數vector是很便宜的。

所以就變成:

  • 信任編譯:要麼靜脈阻塞或移動語義
  • 在堆上分配,並返回一個unique_ptr

但真正的第二點應僅適用於使用那些移動語義沒有多大幫助的幾類:移動語義的成本通常與sizeof的返回成比例,例如std::array<T,10>的大小等於10*sizeof(T),因此它不是這麼好,可能會受益於堆分配+ unique_ptr


切線:您已經信任您的編譯器。你信任它來警告你錯誤,你信任它來警告你有關危險/可能不正確的結構,你相信它將你的代碼正確地轉換成機器裝配,你相信它應用有意義的優化來獲得體面的加速。不要相信一個編譯器在明顯的情況下應用RVO就好像不要用10美元的賬單來信任你的心臟外科醫生:這是你最擔心的問題。 ;)

+1

非常感謝切線! :) – tmaric

1

我確信編譯器會爲valueFun做返回值優化。其中返回值優化不能由編譯器所施加的主要情況:

  • 返回參數
  • 返回基於條件

一個不同的對象因此auto_ptr的是沒有必要的,並且將由於必須使用堆,所以速度更慢。

如果您仍然擔心移動如此大的矢量的代價,您可能需要考慮使用移動語義(C++ 11的std::vector aCopy(std::move(otherVector))),它們幾乎與RVO一樣快,可以使用任何地方(它也保證用於返回值時RVO無法使用。)

我認爲最現代的編譯器支持移動語義(或右值引用技術)在這一點上

+0

「相當確定」是讓我困擾的一點。 :)從我的觀點來看,如果我要在100核心上運行這個東西,並且它會隨着時間的推移而增長,我需要100%確定代碼的功能。 – tmaric