【发布时间】:2018-05-07 23:28:07
【问题描述】:
我看到了这个用户post yesterday。我认为这是输出向量的一种很酷的方式。因此,我输入了一个示例并问自己这与for each 循环相比如何?
template <typename T>
void printVectorO(std::vector<T> &v)
{
std::cout << "Ostream_iterator contents: " << std::endl;
auto start = std::chrono::high_resolution_clock::now();
std::ostream_iterator<T> ost(std::cout, " ");
std::copy(begin(v), end(v), ost);
std::cout << std::endl;
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(time);
std::cout << "Ostream_iterator computation took: " << nano.count() << " nano seconds"<< std::endl;
std::cout << std::endl;
}
template <typename T>
void printVectorC(std::vector<T> &v)
{
std::cout << "For Each Loop contents: " << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (auto && e : v) std::cout << e << " ";
std::cout << std::endl;
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto nano = std::chrono::duration_cast<std::chrono::nanoseconds>(time);
std::cout << "For Each Loop took: " << nano.count() << " nano seconds" << std::endl;
std::cout << std::endl;
}
我用了 3 个向量来测试这个:
std::vector<double> doubles = { 3.15, 2.17, 2.555, 2.014 };
std::vector<std::string> strings = { "Hi", "how", "are", "you" };
std::vector<int> ints = { 3, 2 , 2 , 2 };
我得到了各种结果。当我输出双打时,for each 循环总是优于ostream_iterator(例如 41856 与 11207 和 55198 与 10308 纳秒)。有时,字符串ostream_iterator 胜过for each 循环,而for each 循环和ostream_iterator 几乎与整数并驾齐驱。
这是为什么? ostream_iterator 的幕后发生了什么?在效率和速度方面,我什么时候会在 for each 循环上使用 ostream_iterator?
【问题讨论】:
-
建议添加编译器和优化级别,以帮助建立参考框架。
-
也许在您对
copy的调用周围添加一个循环,并在您的for周围添加一个循环,以重复感兴趣的代码一百万次,以排除可能影响您的时间安排的其他事情。 -
除了 jxh 的注释之外,也许添加一个循环来生成几十万个值放入向量中,这样差异会更加明显(即检查差异是否总是几纳秒 vs . 如果它们按比例增长)。
-
我同意,只有三个值,任何指标都是没有意义的。尝试几千个值。也尝试输出到
std::ostringstream而不是std::cout。输出到std::cout可能会反映有关输出缓冲区刷新的一些伪影。 -
在控制台上显示字符(和滚动控制台)的成本将使两种迭代策略的可忽略的性能差异相形见绌。基准测试有意义的唯一方法是流式传输到 std::ostream ,其基础字符串已经具有足够的容量来防止重新分配。另一种选择是创建自己的 streambuf 派生流缓冲区并将其分配给 ostream。
标签: c++ performance foreach iterator