2013-12-17 161 views
9

雖然在一些遺留代碼項目的工作,我發現這個功能:初始化的std ::矢量:: string的

std::vector<std::string> Object::getTypes(){ 
    static std::string types [] = {"type1","type2", "type3"}; 
    return std::vector<std::string> (types , types +2); 
} 

我可能會寫這爲:

std::vector<std::string> Object::getTypes(){ 
    std::vector<std::string> types; 
    types.push_back("type1"); 
    types.push_back("type2"); 
    types.push_back("type3"); 
    return types; 
} 

是這只是一種風格選擇,還是我缺少的東西?任何幫助將不勝感激。對不起,如果這太基本了。

更新: 重寫同樣的方法居然發現不同類別做一個或其他方式,所以它更曖昧。我會讓他們都一樣,但寧願更好的方法,如果有的話。


編輯

請注意,上述的傳統代碼不正確,因爲它初始化只在陣列的前兩個元素的向量。但是,這個錯誤已經在評論中討論過了,因此應該保留。

正確的初始化應如下:

... 
    return std::vector<std::string> (types, types + 3); 
... 
+2

第一個咒語原則上可以更高效,因爲它不涉及任何記憶重新分配。函數調用也較少。注意在C++ 11中,你可以說'return std :: vector {「type1」,「type2」,「type3」};'。 – juanchopanza

+2

@juanchopanza另外,在該版本中,代碼和數據的隔離更加明顯,因此它在語法上更清晰。 – 2013-12-17 12:45:17

+0

糾正我以前的評論:在C++ 11中,你可以用較少的詞來實現它:'return {「type1」,「type2」,「type3」};'。 – juanchopanza

回答

1

第一個示例中的陣列types被聲明爲靜態。這意味着它只在內存中存在一次。所以有三種選擇返回什麼,他們生活在靜態內存中。然後,當您創建要返回的向量時,您可以通過將數組的開始和結束作爲迭代器來一次性分配它的內存。

通過這樣做,您不需要連續調用push_back這意味着向量將不必重新分配其內存塊。另外,當向量被構造爲返回調用的一部分時,較老的編譯器將會更容易地執行return value optimization

+0

RVO同樣適用於所有代碼。即使使用「較老的」編譯器(其中許多實際上比一些最近的編譯器做得更好)。 –

5

您發現該代碼是更有效的(因爲types[]只分配一次,push_back能/會導致重新分配)。雖然這種差異是微不足道的,除非你在一個(相對較大的)循環中調用getTypes,它根本就不重要(甚至當你在大循環中調用它時也不重要)。

因此,除非它產生具體的性能問題,否則這是一種風格選擇。

9

如果你有一個C++ 11能夠編譯器和庫,返回一個初始化列表應該足夠:

std::vector<std::string> Object::getTypes(){ 
    return {"type1","type2", "type3"}; 
} 
3

基本上這是一個風格的選擇。我可能會做更多的事情

std::vector<std::string> Object::getTypes(){ 
    static std::string types [] = {"type1","type2", "type3"}; 
    return std::vector<std::string> (types, 
        types + (sizeof(types)/sizeof(std::string))); 
} 

它可以讓你改變類型的東西數量,而不必記得更新下一行的計數。

+0

這給了我一個錯誤,如果我嘗試這樣做,「沒有匹配的構造函數初始化'std :: vector '」。起初我認爲我應該像你說的那樣去做,但它不能編譯。 –

+0

@AndresBucci你需要'std :: vector (類型,類型+ sizeof(類型)/ sizeof(std :: string));' – juanchopanza

+1

@AndresBucci - 請參閱編輯,juanchopanza的評論擊敗了我的編輯。基本上,vector沒有(Type *,nelements)構造函數,它有一個(iterator,iterator)構造函數。 –

0

我喜歡用這種迭代器初始化(和C++ 11的統一初始化和初始化器列表)的原因之一是它有助於從代碼中分離數據。

重複push_back很多時候感覺不好,因爲我迫切需要重構它。另外,當你真的只需要用數據初始化容器時,你想看到數據列表,而不是真正的代碼生成數據。您在原始版本中找到的方法更符合該原則。