如果要考虑性能问题,请考虑不要使用 std::back_inserter 填充目标向量(一种涉及任意数量的昂贵目标向量重新分配的方法),调用 std::copy_if 后跟源大小的目标向量通过 dest.erase(iteratorReturnedByCopyIf, dest.end()) - 一种方法,涉及先分配一次,然后再重新分配一次erase()。
数据
代码
#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
long long MeasureMilliseconds(std::function<void()> func, unsigned iterations)
{
auto beginTime = std::chrono::high_resolution_clock::now();
for (unsigned i = 0; i < iterations; ++i)
{
func();
}
auto endTime = std::chrono::high_resolution_clock::now();
long long milliseconds = std::chrono::duration_cast<
std::chrono::milliseconds>(endTime - beginTime).count();
return milliseconds;
}
bool IsEven(int i)
{
return i % 2 == 0;
}
int main()
{
const unsigned Iterations = 300000;
for (size_t N = 0; N <= 100; N += 2)
{
std::vector<int> source(N);
// Populate source with 1,2,...,N
std::iota(std::begin(source), std::end(source), 1);
long long backInserterMilliseconds = MeasureMilliseconds([&]
{
std::vector<int> dest;
std::copy_if(std::begin(source), std::end(source),
std::back_inserter(dest), IsEven);
}, Iterations);
long long sourceSizeAndEraseMilliseconds = MeasureMilliseconds([&]
{
std::vector<int> dest(source.size());
std::vector<int>::iterator copyIfIterator = std::copy_if(
std::begin(source), std::end(source), std::begin(dest), IsEven);
dest.erase(copyIfIterator, dest.end());
}, Iterations);
std::cout << "N=" << N << '\n';
std::cout << "Default-size dest and back_inserter: " <<
backInserterMilliseconds << '\n';
std::cout << " Source-sized dest and erase(): " <<
sourceSizeAndEraseMilliseconds << "\n\n";
}
return 0;
}
代码输出
N=90
Default-size dest and back_inserter: 469
Source-sized dest and erase(): 89
N=92
Default-size dest and back_inserter: 472
Source-sized dest and erase(): 90
N=94
Default-size dest and back_inserter: 469
Source-sized dest and erase(): 92
N=96
Default-size dest and back_inserter: 478
Source-sized dest and erase(): 92
N=98
Default-size dest and back_inserter: 471
Source-sized dest and erase(): 93
N=100
Default-size dest and back_inserter: 480
Source-sized dest and erase(): 92
参考文献
[alg.copy]
Qt ScatterChart