Это расширение для двух ответов, уже представленных выше, поскольку производительность во время исполнения показалась темой в комментариях. Я бы добавил его в качестве комментариев, но у меня пока нет этой привилегии.
Я тестировал 2 реализаций для выполнения время выполнения с помощью Visual Studio 2015:
Использование stringstream:
std::stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
Использование аккумулировать:
std::string result = std::accumulate(std::next(vec.begin()), vec.end(),
std::to_string(vec[0]),
[&delimiter](std::string& a, uint8_t b) {
return a + delimiter+ std::to_string(b);
});
return result;
выпуска производительность сборки во время выполнения был близок с несколькими тонкостями.
Реализация накопления была немного быстрее (20-50 мс, ~ 10-30% от общего времени выполнения (~ 180 мс) на 1000 итераций по 256-элементному вектору).Однако реализация accumulate
была только быстрее, когда параметр a
для функции лямбда был передан по ссылке. Передача параметра a
по значению привела к аналогичной разнице во времени выполнения в пользу реализации stringstream
. Реализация accumulate
также улучшила некоторые, когда возвращаемая строка результата была возвращена напрямую, а не назначена локальной переменной, которая была немедленно возвращена. YMMV с другими компиляторами C++.
Сборка Debug была в 5-10 раз медленнее, используя accumulate
, поэтому я думаю, что добавленное строковое создание, указанное в нескольких комментариях выше, разрешено оптимизатором.
Я искал конкретную реализацию, используя vector
значений uint8_t
. Полный тестовый код следующим образом:
#include <vector>
#include <iostream>
#include <sstream>
#include <numeric>
#include <chrono>
using namespace std;
typedef vector<uint8_t> uint8_vec_t;
string concat_stream(const uint8_vec_t& vec, string& delim = string(" "));
string concat_accumulate(const uint8_vec_t& vec, string& delim = string(" "));
string concat_stream(const uint8_vec_t& vec, string& delimiter)
{
stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
}
string concat_accumulate(const uint8_vec_t& vec, string& delimiter)
{
return accumulate(next(vec.begin()), vec.end(),
to_string(vec[0]),
[&delimiter](string& a, uint8_t b) {
return a + delimiter + to_string(b);
});
}
int main()
{
const int elements(256);
const int iterations(1000);
uint8_vec_t test(elements);
iota(test.begin(), test.end(), 0);
int i;
auto stream_start = chrono::steady_clock::now();
string join_with_stream;
for (i = 0; i < iterations; ++i) {
join_with_stream = concat_stream(test);
}
auto stream_end = chrono::steady_clock::now();
auto acc_start = chrono::steady_clock::now();
string join_with_acc;
for (i = 0; i < iterations; ++i) {
join_with_acc = concat_accumulate(test);
}
auto acc_end = chrono::steady_clock::now();
cout << "Stream Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(stream_end - stream_start).count() << " ms" << endl;
cout << " result: " << join_with_stream << endl;
cout << "Accumulate Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(acc_end - acc_start).count() << " ms" << endl;
cout << " result:" << join_with_acc << endl;
return 0;
}
Да, было бы неплохо, если бы компилятор любезно сказал вам, какого типа он ожидал. Кстати, вы получите запятую после своего последнего элемента. – CashCow
Самый элегантный способ - использовать boost :: algorithm :: join() для этого, как описано в http://stackoverflow.com/a/6334153/2056686 – StefanQ