Я использую copy_if неправильно?
Я использую visual studio 2010, и я пытаюсь использовать std:: copy_if,
Я хочу скопировать все значения, удовлетворяющие предикату. Например:
struct comp
{
bool operator()(const int i) { return i == 5 || i == 7; }
};
int main()
{
array<int, 10> arr = { 3, 2, 5, 7, 3, 5, 6, 7 };
vector<int> res;
copy_if(arr.begin(), arr.end(), res.begin(), comp());
for(int i = 0; i < res.size(); i++)
{
cout << res[i] << endl;
}
return 0;
}
Но когда я запускаю этот код, я получаю: векторный итератор не увеличивается.
Ответы
Ответ 1
Алгоритм copy_if выглядит примерно так (взято из MSVC2010):
template<class InIt, class OutIt, class Pr> inline
OutIt copy_if(InIt First, InIt Last, OutIt Dest, Pr Pred)
{
for (; First != _Last; ++First)
if (Pred(*_First))
*Dest++ = *First;
return (Dest);
}
И как вы можете видеть, copy_if не делает push_back, он просто копирует значение в позиции, где находится итератор, а затем увеличивает итератор.
Вместо этого вы хотите использовать std:: back_inserter, который выталкивает элемент обратно вашего вектора. И если вы используете MSVC2010, вы можете использовать Lambda вместо объекта функции, который Microsoft предлагает как расширение (С++ 0x)
int main()
{
array<int, 10> arr = { 3, 2, 5, 7, 3, 5, 6, 7 };
vector<int> res;
copy_if(arr.begin(), arr.end(), back_inserter(res),[](const int i) { return i == 5 || i == 7; });
for(unsigned i = 0; i < res.size(); i++)
cout << res[i] << endl;
return 0;
}
Ответ 2
Вы можете использовать итератор вывода:
copy_if(arr.begin(), arr.end(), std::back_inserter(res), comp());
Ответ 3
Если первична проблема, рассмотрите вместо использования std:: back_inserter для заполнения целевого вектора (подход, который включает в себя произвольное количество дорогостоящих переадресаций назначения вектора), вызовите std:: copy_if с указанным целевым вектором источника by dest.erase(iteratorReturnedByCopyIf, dest.end()) - подход, который включает в себя одно распределение спереди, а затем одно перераспределение для erase().
Данные
![С++ std:: copy_if производительность с помощью алгоритма дешифрования]()
код
#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
Ответ 4
Зарезервируйте размер массива. hidayat дает причину этого.
res.resize(arr.size());