2012-12-05 49 views
12

積累,我有以下代碼C++與移動而不是複製

auto adder = [](string& s1, const string& s2)->string&& 
    { 
     if (!s1.empty()) 
     s1 += " "; 
     s1 += s2; 
     return move(s1); 
    }; 

    string test; 
    test.reserve(wordArray.size() * 10); 
    string words = accumulate(wordArray.begin(), wordArray.end(), 
     move(test), adder); 

我想在這裏是爲了避免字符串拷貝。不幸的是,這不是通過vs2012實現累計來完成的。內部積累調用另一個函數_Accumulate和右值函數在進程中丟失。

據我改爲調用_Accumulate功能,像這樣

string words = _Accumulate(wordArray.begin(), wordArray.end(), 
    move(test), adder); 

我得到預期的性能增益。

必須重寫std庫以考慮右值參數嗎?

有沒有其他一些方法我可以使用積累來完成我想要的東西而不會欺騙太多?

+1

你'test'不是右值。 lambda中的's1'不是右值 –

回答

4

檢查最近的文章C++ 11個匯票(N3337.pdf)我們可以看出,被指定的std ::累加的效果

通過初始化與累加器ACC計算其結果的一個初始值初始值,然後 按順序對每個迭代器i按照acc = acc + * i或acc = binary_op(acc,* i)修改,範圍爲 [first,last)。

所以,實際上標準是禁止使用std ::像這樣的老累加值移動實現:

template <class InputIterator, class T, class BinOp> 
T accumulate (InputIterator first, InputIterator last, T init, BinOp binop) 
{ 
    while (first!=last) { 
    init = binop(std::move(init), *first); 
    ++first; 
    } 
    return init; 
} 

這是你的情況很不幸。

選項(1):實現此移動感知累積自己。

選擇(2):繼續使用仿函數像

struct mutating_string_adder { 
    string operator()(string const& a, string const& b) const {return a+b;} 
    string operator()(string & a, string const& b)  const {a += b; return std::move(a);} 
    string operator()(string && a, string const& b)  const {a += b; return std::move(a);} 
}; 

注意,我在這裏做不使用右值引用返回類型。這是有意的,因爲它可以避免懸而未決的引用問題,例如在最後一個重載被選中並且'a'被初始化以引用臨時對象的情況下。所有的操作符+字符串重載也有意返回值。

除此之外,您可能希望將std :: copy與std :: stringstream和輸出流迭代器結合使用。

附錄:備用mutating_string_adder一些局部的完美轉發:

struct mutating_string_adder { 
    template<class T, class U> 
    std::string operator()(T && a, U && b) const { 
    return std::move(a) + std::forward<U>(b); 
    } 
}; 
+0

'mutating_string_adder' - 第二個運算符(),a是左值,因此移動不會執行任何操作。但是,我不確定第一個operator()是否應該使用move。 –

+0

@BЈовић:std :: move的目的是將一個左值變成一個右值。所以,當然,std :: move會做一些事情。如果我在返回語句中刪除了std :: move,則返回值將被複制而不是構建。第一次重載不需要使用std :: move,因爲a + b已經是右值。 – sellibitze

+0

移動感知積累工作正常,沒有任何地方的副本和相同的保留區域一直使用 –

相關問題