std::accumulate makes a ton of copies internally. In fact it's 2x the size of the number of elements in the iterator range. To fix, use std::ref and std::reference_wrapper for the initial state. std::shared_ptr is also a possibility if the accumulated state must be dynamically allocated for some reason. Live code on wandbox.
Update: Please see alternative solutions in the comments section.
Update: Please see alternative solutions in the comments section.
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>
#include <functional>
struct Vector : public std::vector<int> {
Vector(std::initializer_list<int> il) : std::vector<int>(il){
std::cout << "Vector(std::initializer_list)\n";
}
Vector() {
std::cout << "Vector()\n";
}
Vector(const Vector &v) : std::vector<int>(v) {
std::cout << "Vector(const Vector &)\n";
}
Vector & operator = (const Vector &v) {
if (this != &v) {
std::vector<int>::operator=(v);
std::cout << "Vector& Vector::operator=(const Vector &)\n";
}
return *this;
}
Vector & operator = (Vector && v) {
if (this != &v) {
std::vector<int>::operator=(std::move(v));
std::cout << "Vector& Vector::operator=(Vector&&)\n";
}
return *this;
}
Vector(Vector&& v) : std::vector<int>(std::move(v)) {
std::cout << "Vector(Vector&&)\n";
}
};
void copy_accumulate(Vector &v) {
Vector v2 = std::accumulate(v.begin(), v.end(), Vector(),
[](Vector & v, int i) {
v.push_back(i);
return v;
});
std::cout << "size of v2 = " << v2.size() << "\n";
}
void nocopy_accumulate(Vector &v) {
Vector init;
Vector v2 = std::accumulate(v.begin(), v.end(), std::ref(init),
[](std::reference_wrapper<Vector> v, int i) {
v.get().push_back(i);
return v;
});
std::cout << "size of v2 = " << v2.size() << "\n";
}
int main()
{
Vector v { 1, 2, 3, 4 };
copy_accumulate(v);
std::cout << "=============\n";
nocopy_accumulate(v);
}
Comments
void copy_accumulate(Vector &v) {
Vector v2 = std::accumulate(v.begin(), v.end(), Vector(),
[](Vector & v, int i)->Vector& {
v.push_back(i);
return v;
});
std::cout << "size of v2 = " << v2.size() << "\n";
}
Vector v2 = std::accumulate(v.begin(), v.end(), Vector(),
[] (Vector& v, int i) {
v.push_back(i);
return std::ref(v);
});
std::cout << "size of v2 = " << v2.size() << "\n";
}