vector<string> v(10, "foo");
string concat = accumulate(v.begin(), v.end(), string(""));
Этот пример - просто плохое программирование в любом стандарте C ++. Это эквивалентно этому:
string tmp;
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
tmp = tmp + "foo"; //copy tmp, append "foo", then copy the result back into tmp
Семантика перемещения C ++ 11 будет заботиться только о части «скопировать результат обратно в tmp» уравнения. Начальные копии из tmp по-прежнему будут копиями. Это классический алгоритм Шлемеля-живописца , но даже хуже, чем обычный пример, использующий strcat
в C.
Если бы accumulate
просто использовал +=
вместо +
и =
, он бы избежал всех этих копий.
Но C ++ 11 дает нам способ добиться большего успеха, оставаясь лаконичным, используя лямбда-функцию:
string concat;
for_each(v.begin(), v.end(), [&](const string &s){ concat += s; });
РЕДАКТИРОВАТЬ: Я полагаю, что разработчик стандартной библиотеки мог бы реализовать accumulate
с перемещением операнда на +
, поэтому tmp = tmp + "foo"
станет tmp = move(tmp) + "foo"
, и это в значительной степени решит эту проблему. Я не уверен, будет ли такая реализация строго соответствовать. Ни GCC, ни MSVC, ни LLVM в настоящее время не делают этого. И поскольку accumulate
определено в <numeric>
, можно предположить, что оно предназначено только для использования с числовыми типами.