C++ for循环效率优化
测试代码
main.cpp源代码
#include <iostream>
#include <vector>
#include "timer.h"
#include <algorithm>
struct QCJ
{
int a;
float b;
};
int main(int argc, char **argv)
{
Timer timer;
std::map<std::string, double> map_time;
std::string log;
const int size = 100000000;
std::vector<QCJ> source(size);
std::vector<QCJ> target(size);
// method 1 for + push_back 531.456ms.
timer.tic();
for (size_t i = 0; i < source.size(); i++)
{
int a = source[i].a;
float b = source[i].b;
target.push_back(source[i]);
}
double time_m1 = timer.toc(true);
log = "Method 1 for + push_back";
std::cout << log << ": " << time_m1 << "ms." << std::endl;
// method 1-1 for iterator + push_back 144.177ms.
target.clear();
timer.tic();
for (auto itr = source.begin(); itr != source.end(); ++itr)
{
int a = itr->a;
float b = itr->b;
target.push_back(*itr);
}
double time_m1_1 = timer.toc(true);
log = "method 1-1 for iterator + push_back";
std::cout << log << ": " << time_m1_1 << "ms." << std::endl;
// method 2 for + emplace 297.366ms.
target.clear();
timer.tic();
for (size_t i = 0; i < source.size(); i++)
{
int a = source[i].a;
float b = source[i].b;
target.emplace_back(source[i]);
}
double time_m2 = timer.toc(true);
std::cout << "method 2 for + emplace: " << time_m2 << "ms." << std::endl;
// method 2-1 for iterator + emplace_back 296.168ms.
target.clear();
timer.tic();
for (auto itr = source.begin(); itr != source.end(); ++itr)
{
int a = itr->a;
float b = itr->b;
target.emplace_back(*itr);
}
double time_m2_1 = timer.toc(true);
std::cout << "method 2-1 for iterator + emplace_back: " << time_m2_1 << "ms." << std::endl;
// method 3 for2 + push_back 148.236ms.
target.clear();
timer.tic();
for (auto src : source)
{
int a = src.a;
float b = src.b;
target.push_back(src);
}
double time_m3 = timer.toc(true);
std::cout << "method 3 for2 + push_back: " << time_m3 << "ms." << std::endl;
// method 4 for2 + emplace_back 328.124ms.
target.clear();
timer.tic();
for (auto src : source)
{
int a = src.a;
float b = src.b;
target.emplace_back(src);
}
double time_m4 = timer.toc(true);
std::cout << "method 4 for2 + emplace_back: " << time_m4 << "ms." << std::endl;
// method 5 for3 & + push_back 143.673ms.
target.clear();
timer.tic();
for (auto &src : source)
{
int a = src.a;
float b = src.b;
target.push_back(src);
}
double time_m5 = timer.toc(true);
std::cout << "method 5 for3 & + push_back: " << time_m5 << "ms." << std::endl;
// method 6 for3 & + emplace_back 287.063ms.
target.clear();
timer.tic();
for (auto &src : source)
{
int a = src.a;
float b = src.b;
target.emplace_back(src);
}
double time_m6 = timer.toc(true);
log = "method 6 for3 & + emplace_back";
std::cout << log << ": " << time_m6 << "ms." << std::endl;
// method 7 for 临时引用 & + push_back 145.094ms.
target.clear();
timer.tic();
for (size_t i = 0; i < source.size(); i++)
{
auto &QCJ = source[i];
int a = QCJ.a;
float b = QCJ.b;
target.push_back(QCJ);
}
double time_m7 = timer.toc(true);
log = "method 7 for 临时引用 & + push_back";
std::cout << log << ": " << time_m7 << "ms." << std::endl;
// method 8 for 临时引用 & + emplace_back 289.195ms.
target.clear();
timer.tic();
for (size_t i = 0; i < source.size(); i++)
{
auto &QCJ = source[i];
int a = QCJ.a;
float b = QCJ.b;
target.emplace_back(QCJ);
}
double time_m8 = timer.toc(true);
log = "method 8 for 临时引用 & + emplace_back";
std::cout << log << ": " << time_m8 << "ms." << std::endl;
// method 9 for 临时引用 + std::copy 72.3075ms.
target.clear();
timer.tic();
for (size_t i = 0; i < source.size(); i++)
{
auto &QCJ = source[i];
int a = QCJ.a;
float b = QCJ.b;
}
std::copy(source.begin(), source.end(), target.begin());
double time_m9 = timer.toc(true);
log = "method 9 for 临时引用 + std::copy";
std::cout << log << ": " << time_m9 << "ms." << std::endl;
// method 10 for3 & + std::copy 70.3496ms.
target.clear();
timer.tic();
for (auto &src : source)
{
int a = src.a;
float b = src.b;
}
std::copy(source.begin(), source.end(), target.begin());
double time_m10 = timer.toc(true);
log = "method 10 for3 & + std::copy";
std::cout << log << ": " << time_m10 << "ms." << std::endl;
// method 11 for_each + std::copy 71.0002ms.
target.clear();
int aa;
float bb;
timer.tic();
auto Function = [&](QCJ &t){aa = t.a; bb = t.b;};
std::for_each(source.begin(), source.end(), Function);
std::copy(source.begin(), source.end(), target.begin());
double time_m11 = timer.toc(true);
log = "method 11 for_each + std::copy";
std::cout << log << ": " << time_m11 << "ms." << std::endl;
结果:
Method 1 for + push_back: 531.456ms.
method 1-1 for iterator + push_back: 144.177ms.
method 2 for + emplace: 297.366ms.
method 2-1 for iterator + emplace_back: 296.168ms.
method 3 for2 + push_back: 148.236ms.
method 4 for2 + emplace_back: 328.124ms.
method 5 for3 & + push_back: 143.673ms.
method 6 for3 & + emplace_back: 287.063ms.
method 7 for 临时引用 & + push_back: 145.094ms.
method 8 for 临时引用 & + emplace_back: 289.195ms.
method 9 for 临时引用 + std::copy: 72.3075ms.
method 10 for3 & + std::copy: 70.3496ms.
method 11 for_each + std::copy: 71.0002ms.
结论
-
耗时:
for(auto itr = items.begin(); itr != items.end(); itr++)
相当于for(auto & item : items)
<for(auto item : items)
<for(size_t i = 0; i < items.size(); ++i)
-
耗时: 引用取值 < 拷贝取值
-
耗时: std::copy < 遍历赋值
-
emplace_back效率不一定比push_back高;在 vector 这样的序列容器中,
emplace_back
比右值参数的push_back
少做一次移动构造, 比左值参数的push_back
少做一次拷贝构造;
for循环优先使用 for(auto itr = items.begin(); itr != items.end(); itr++)
或 for(auto & item : items)
或 for_each
拷贝vector数组时,优先使用std::copy