2008-12-19 49 views
2

簡單的問題;什麼更好,爲什麼?針對調整大小()+迭代器的循環push_back



    out.resize(in.size()); 
    T1::iterator outit = out.begin(); 
    for(inIt = in.begin() to end, ++inIt, ++outIt) 
     *outit = *inIt 
OR 

    out.erase(); 
    for(inIt = in.begin() to end, ++inIt) 
     out.push_back(inIt); 


我假設push_back中隱含的內存分配值得避免,但要確保。

由於

編輯: 感謝您的OUT =在建議球員)。我擺弄實際的代碼是:


template//can't stop the browser ignoring th class T1, class T2 in angle brackets 
bool asciihex(T1& out, const T2& in) 
{ 
    //out.erase(); 
    out.resize(in.size()/2); 
    if(std::distance(in.begin(), in.end()) % 2)//use distance rather than size to minimise the requirements on T2? 
     return false; 
    for(T2::const_iterator it = in.begin(); it != in.end(); it += 2) 
    { 
     out.push_back(((((*it > '9' ? *it - 0x07 : *it) - 0x30) '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f)); 
    } 
    return true; 
} 

template 
bool asciihex(T1& out, const T2& in) 
{ 
    size_t size = in.size(); 
    if(size % 2)//use distance rather than size to minimise the requirements on T2? 
     return false; 
    out.resize(size/2); 
    T1::iterator outit = out.begin(); 
    for(T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit) 
    { 
     *outit = ((((*it > '9' ? *it - 0x07 : *it) - 0x30) '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f); 
    } 
    return true; 
} 

編輯:我已標記的push_back的答案,因爲它似乎是共識,因此,更給其他人同樣的問題非常有用。然而,我最終使用迭代器方法作爲我感興趣的容器類之一不支持push_back ...里程不同。

+0

我希望這只是供您個人使用的玩具代碼? – Thorsten79 2008-12-29 09:41:39

+0

@ Thorsten79:爲什麼? – Patrick 2008-12-29 12:36:37

回答

4

第二,如果你關心多個擴展使用out.reserve()。添加到矢量中的正確答案几乎總是push_back或back_inserter,它可以避免一些可能的問題(例如,保證,構造函數,例如寫作過後),您必須注意其他方法。

2

第二個,只要你保留正確的容量第一。

一個問題,我看到(除了風格)是在第一位的,如果你的副本任務拋出,你已經採取了,應該給你的有力保證的操作,並用它來給難保。

1

那麼這有什麼問題?

out = in; 

難道你不認爲那會有最好的行爲嗎?如果沒有,那很糟糕。

此外,您的兩個代碼示例應該

out.resize(in.size()); 
T1::iterator outIt = out.begin(); 
for(T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt, ++outIt) 
    *outIt = *inIt; 

out.erase(out.begin(), out.end()); 
for(T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt) 
    out.push_back(*inIt); 
+0

道歉,但我簡化了示例,並在for循環中使用了一些僞代碼 – Patrick 2008-12-19 16:29:42

2

如果你關心保護in然後執行:

out = in; 

如果不這樣做,那麼做:

std::swap(out, in); 

如果出來,在不同類型的容器,那麼試試這個:

out.erase(out.begin(), out.end()); 
// if it's a vector or other contiguous memory container, you'll want to reserve first 
// out.reserve(in.size()); 
std::copy(in.begin(), in.end(), back_inserter(out)); 
1

如果你正在處理簡單值喜歡整數或雙打都不會有問題(性能明智)如果調整和設置或保留和push_back。

如果您正在應對有顯著的構造,最好是使用第二的push_back爲基礎的方法更復雜的對象。

如果對象沒有一個有意義的默認構造函數那麼的push_back方法是唯一可行的技術。

1

我有一種情況,在基於push_back的解決方案中,與在調整大小的矢量上使用[]運算符的解決方案相比,性能更差。造成差異的原因是檢查矢量是否需要在每次執行push_back時擴大其容量。

更糟糕的是,編譯器認爲它不能內聯push_back的調用,但它確實將保留邏輯內聯到push_back方法中。這給了函數調用的開銷,並且調用的函數沒有多大意義。即使在一些force_inline按摩之後,它的速度也不如基於[]運算符的循環。

基於迭代器或[]運算符的循環將不會執行任何操作,除非寫入該值,至少在處理簡單類型時不會執行任何操作。如果使用更高級的類型,調整矢量大小時默認構造函數的成本可能會破壞潛在的勝利。無論如何,如果你的程序大部分時間都用在這些循環中,我肯定你應該對不同的解決方案進行基準測試,看看是否有任何性能可以通過使用其中一種解決方案來獲得。如果你沒有在你描述的函數中花費大量的執行時間,你不應該在乎這篇文章:)

0

我更喜歡push_back在數組賦值上,因爲push_back可以使用或不使用randomaccessiterators。數組分配需要它們。如果您現在強制randomaccessiterators,您將來無法輕鬆更改容器。當然,爲了避免調整大小問題,你可以調用vector :: capacity而不是調整大小。