2010-07-30 137 views
21

這個問題很愚蠢,但我需要以非常有效的方式來完成 - 它將在我的代碼中重複執行。我有一個返回一個向量的函數,我必須將返回的值添加到另一個向量中,逐個元素。很簡單:如何通過兩個STL向量的元素添加元素?

vector<double> result; 
vector<double> result_temp 
for(int i=0; i< 10; i++) result_temp.push_back(i); 

result += result_temp //I would like to do something like that. 
for(int i =0; i< result_temp.size();i++)result[i] += result_temp[i]; //this give me segfault 

,我試圖做的數學運算是

U [i] = U [I] + V [I]對於所有i

可以做些什麼?

感謝

編輯:添加了一個簡單的初始化,因爲這是不是問題的關鍵。應該如何初始化結果?

+5

你能發佈一些編譯代碼? 「這給了我一個段錯誤」在沒有看到這些向量是如何初始化的情況下並不是特別有用。最可能的問題是其中一個向量比另一個長。在沒有看到所有代碼的情況下很難確定代碼是錯誤的:-) – 2010-07-30 23:48:10

+0

http://www.boost.org/doc/libs/1_43_0/libs/numeric/ublas/doc/operations_overview.htm – Anycorn 2010-07-30 23:57:41

回答

28

如果您試圖將一個vector附加到另一個,您可以使用類似以下內容。這些是我的事業圖書館一 - 二operator+=重載std::vector:一個附加到vector一個單一的元素,另外追加整個vector

template <typename T> 
std::vector<T>& operator+=(std::vector<T>& a, const std::vector<T>& b) 
{ 
    a.insert(a.end(), b.begin(), b.end()); 
    return a; 
} 

template <typename T> 
std::vector<T>& operator+=(std::vector<T>& aVector, const T& aObject) 
{ 
    aVector.push_back(aObject); 
    return aVector; 
} 

如果你想進行求和(即,創建包含的另外兩個vector S中的元素之和新vector),你可以使用類似以下內容:

#include <algorithm> 
#include <functional> 

template <typename T> 
std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b) 
{ 
    assert(a.size() == b.size()); 

    std::vector<T> result; 
    result.reserve(a.size()); 

    std::transform(a.begin(), a.end(), b.begin(), 
        std::back_inserter(result), std::plus<T>()); 
    return result; 
} 

你可以同樣實現了operator+=超載。

+0

謝謝,但我並沒有試圖將值附加到向量的末尾,我試圖將矢量元素的現有值與另一個向量的值相加。矢量的大小始終是固定的。 – Ivan 2010-07-30 23:59:16

+2

@Ivan:看到編輯;直到我看到你的評論回覆格雷格的回答時,我並不完全確定你在找什麼。 – 2010-07-31 00:00:11

+2

@詹姆斯忽略我的原始評論 - 現在你已經看中和相關的代碼:) – 2010-07-31 00:00:42

0

我與@詹姆斯麥克奈利斯 - 這段代碼似乎是正確的,只要resultresult_temp是相同的長度。

此外 - 爲什麼你聲明result,但使用變量result_v - 是如何實際編寫的代碼?如果是這樣,這是一個問題

1

您需要首先將result初始化爲全零;只是聲明變量並不實際分配任何元素。

試試這個:

vector<double> result(10); // default-initialize to 10 elements 
vector<double> result_temp; 
for(int i=0; i< 10; i++) 
    result_temp.push_back(i); 

for(int i =0; i< result_temp.size();i++) 
    result[i] += result_temp[i]; 
0

的代碼看起來不錯,但我的第一個傾向是改變任何代碼填充向量與值添加到值在第一載體採取的參考第一個矢量並直接添加到它而不是創建一個返回的新矢量。這只是低效率。

如果你不能以這種方式改變函數,也許你可以改變它,以便它引用一個清除的向量,然後插入這些值,這樣你就不會複製向量。如果你做得很多,這可能會很昂貴。

如果您試圖儘可能快地獲得此代碼,那麼您應該使用迭代器的預增量而不是後增量。在處理重載操作符而不是內置類型時,後增量創建的臨時操作無法優化。所以,你一直在創建和銷燬循環的每一次迭代。編輯:正如在評論中指出的那樣,你在這裏使用索引而不是迭代器(我顯然沒有給予足夠的關注),所以這個建議在這裏並不適用。但是,在使用迭代器的的情況下,它仍然有效。除此之外,如果您試圖將兩個向量的所有元素都添加到其中,那麼您擁有的解決方案可能與您將要獲得的解決方案一樣高效。如果你關心的是將一個向量的元素插入另一個向量,有更好的方法,但是如果你只是將它們的值加在一起,你看起來不錯。我期望使用任何STL算法最多隻會因爲額外的函數調用而快速且可能較慢,但您可能必須對其進行配置才能確定。

+1

「你應該使用迭代器而不是後增量進行預增量」。沒錯,但他沒有使用迭代器,他使用了整數索引。很難做出前和後增量之間的表現案例;-) – 2010-07-31 00:30:10

+0

啊,很好的捕獲。我沒有給予足夠的關注。我很少使用索引而不是迭代器,並且我對後增加的直覺反應非常消極。除非需要後期增量,否則我總是堅信使用前增量。這樣,您永遠不必擔心臨時性是否會被優化。然而,在這種情況下,編譯器應該沒有問題優化它,後增量和預增量一樣有效。 – 2010-07-31 01:07:11

+0

是的,即使除了可能出現的性能問題,我還是喜歡預先增量,但是由於有爭議的原因,我認爲它更清晰可讀。 「Increment i」拼寫爲「++ i」。很少有人同意。 – 2010-07-31 02:23:34

25

它肯定看起來像問題是存取result不存在的值。 tzaman說明了如何初始化結果到10個元素,每個具有0值

現在需要調用transform函數(從<算法>),應用plus功能對象(從<官能>):

std::transform(result.begin(), result.end(), result_temp.begin(), 
       result.begin(), std::plus<double>()); 

此操作重複執行resultresult_temp,應用plus,該值增加了兩倍,並將總和寫回result

0

如果您的代碼是segfaulting,那麼這是一個正確性問題,而不是效率問題。

爲了實現 「U [i] = U [I] + V [I]對於所有我」,我會做基本上你做了什麼:

assert(u.size() == v.size()); // will fail with your initialization code, since 
           // your "result" has size 0, not size 10. 
           // perhaps do u.resize(v.size()); 
for (size_t i = 0; i < u.size(); ++i) { 
    u[i] += v[i]; 
} 

如果你真的關心你的程序的性能(也就是說,你已經寫了一個基本的版本,它太慢了,以至於你的程序沒有達到某些要求,並且你已經證明這是大部分時間都需要的代碼),那麼你可以嘗試:

  • 在您的編譯器中切換大量優化(實際上,即使沒有性能問題,我通常會默認執行該操作),
  • 使用迭代器而不是索引(很少有很大的區別,但很容易比較兩者),展開循環一點點(可以使速度有所不同,但對特定情況非常敏感,並且它鼓勵編碼錯誤)。
  • 查看平臺特定的SIMD指令而不是C++。然後對這些指令使用嵌入式彙編程序或編譯器內在函數。

儘管如此,在代碼正確之前,您沒有業務擔心性能問題;-)。 「讓它工作,把它做好,讓它快」是一個合理的座右銘,雖然通常你不需要走到第3步。

std::valarray實際上正是你想要的operator+=。在使用valarrays替換所有矢量之前,請注意,這並不一定意味着它比任何一個簡單的循環都「更有效」 - 我不知道實施者採取的措施有多嚴重valarray。您可以隨時查看實施中的來源。我也不知道爲什麼valarray的多數據運算功能沒有被定義爲vector的一部分,但通常有一個原因。

+0

就像座右銘。 – Vincent 2014-08-19 12:56:05

6

喬恩·裏德的回答的一個具體的例子:

std::array<double,3> a = {1, 2, 3}; 
std::array<double,3> b = {4, 5, 6}; 
std::transform(a.begin(), a.end(), b.begin(), a.begin(),std::plus<double>()); 
ASSERT_TRUE(a[0] == 5); 
ASSERT_TRUE(a[1] == 7); 
ASSERT_TRUE(a[2] == 9);