Efficient accumulate

I would break this into two operations, first std::accumulate to obtain the total length of the string that needs to be created, then a std::for_each with a lambda that updates the local string:

std::string::size_type total = std::accumulate(foo.begin(), foo.end(), 0u, 
                [](std::string::size_type c, std::string const& s) {
                    return c+s.size() 
                });
std::string result;
result.reserve(total);
std::for_each(foo.begin(), foo.end(), 
              [&](std::string const& s) { result += s; });

The common alternative to this is using expression templates, but that does not fit in an answer. Basically you create a data structure that maps the operations, but does not execute them. When the expression is finally evaluated, it can gather the information it needs upfront and use that to reserve the space and do the copies. The code that uses the expression template is nicer, but more complicated.


Using std::accumulate efficiently without any redundant copies is not obvious.
In addition to being reassigned and passed into and out-of the lambda, the accumulating value may get copied internally by the implementation.
Also, note that std::accumulate() itself takes the initial value by-value, calling a copy-ctor and thus, ignoring any reserve()s done on the source of the copy (as suggested in some of the other answers).

The most efficient way I found to concatenate the strings is as follows:

std::vector<std::string> str_vec{"foo","bar"};

// get reserve size:
auto sz = std::accumulate(str_vec.cbegin(), str_vec.cend(), std::string::size_type(0), [](int sz, auto const& str) { return sz + str.size() + 1; });

std::string res;
res.reserve(sz);
std::accumulate(str_vec.cbegin(), str_vec.cend(),
   std::ref(res), // use a ref wrapper to keep same object with capacity
   [](std::string& a, std::string const& b) -> std::string& // must specify return type because cannot return `std::reference_wrapper<std::string>`.
{                                                           // can't use `auto&` args for the same reason
   a += b;
   return a;
});

The result will be in res.
This implementation has no redundant copies, moves or reallocations.


Try the following

res=std::accumulate(foo.begin(),foo.end(),res,
  [](string &rs, const string &arg) -> string & { return rs+=arg; });

Before this call maybe there is a sence to call

std::string::size_type n = std::accumulate( foo.begin(), foo.end(), 
   std::string::size_type( 0 ),
   [] ( std::string_size_type n, const std::string &s ) { return ( n += s.size() ); } );

res.reserve( n );