在啥情况下你应该更喜欢使用 std::copy 写入 cout?
Posted
技术标签:
【中文标题】在啥情况下你应该更喜欢使用 std::copy 写入 cout?【英文标题】:Under what circumstances should you prefer to write to cout using std::copy?在什么情况下你应该更喜欢使用 std::copy 写入 cout? 【发布时间】:2020-01-27 20:25:39 【问题描述】:我一直在阅读 Scott Meyers 的“Effective STL”,我注意到书中有很多例子,他通过使用std::copy
将元素复制到std::cout
来打印容器的内容。与使用基于范围的for
循环相比,这对我来说很难阅读(也许我只需要习惯它?)
// Given the following
std::vector<int> values = 1, 2, 3, 4, 5, 6, 7, 8 ;
// Print using `std::copy`
std::copy(values.begin(), values.end(), std::ostream_iterator<int>(std::cout, ", "));
// Print using a loop
for (const auto value : values)
std::cout << value << ", ";
这篇文章似乎表明使用std::copy
没有显着的性能提升:
is std::copy faster than std::cout for output?
有些人真的觉得std::copy
方法比基于范围的for
循环更具可读性吗?
如果我只想打印一半的值...
std::copy(values.begin(), values.begin() + values.size()/2, std::ostream_iterator<int>(std::cout, ", "));
...但即使那样我也可以这样做:
for (auto it = values.begin(); it != values.begin() + values.size()/2; ++it)
std::cout << *it << ", ";
所以我的问题是为什么有人更喜欢std::copy
方法?是否有任何情况可以证明std::copy
确实是更好的选择(或唯一的选择)?
【问题讨论】:
我认为这归结为纯粹基于意见。一般来说,标准算法不是魔法,你总是可以用手写循环替换它们,反之亦然,所以它主要是关于风格和偏好 请注意,您的最后一个示例在使用非随机访问迭代器时存在问题。例如std::list
。你不能iter + n
,尽管你可以std::next(iter, n)
,但代价是线性复杂度。
有建议说:“没有原始循环”。如果您同意这一点,那么std::copy
就是解决方案。就个人而言,我不介意微不足道的原始循环,因此我将范围用于整个范围,或者将 copy
用于范围的任何部分。
也就是说,一旦我们得到std::span
,我可能会使用span
和远程for。
检查该书的出版时间。它可能完全不了解 C++11,其中包括 auto
变量(至少是那些具有当前含义的变量)和基于范围的 for 循环。
【参考方案1】:
你可以在cppreference查看可能的实现:
template<class InputIt, class OutputIt> OutputIt copy(InputIt first, InputIt last, OutputIt d_first) while (first != last) *d_first++ = *first++; return d_first;
这并没有什么神奇之处。它实际上只是一个将元素从Input
复制到Output
的循环。当然,它不使用基于范围的 for 循环(它有迭代器而不是容器)。它使用while
而不是for
,这只是外观上的区别。
是否有任何情况可以证明 std::copy 确实是更好的选择(或唯一的选择)?
没有。您始终可以手动编写与算法相同的代码。考虑到标准算法不应该比手写代码更好。它们应该和手写代码一样好,而不是更糟。真正的好处是,使用算法可以减少出错的空间,并且更容易识别。写一个复制东西的循环有很多不同的方法,但只有一个std::copy
,这实际上有助于阅读代码。
所以这一切都归结为意见......
真的有人觉得 std::copy 方法比基于范围的 for 循环更具可读性吗?
是的,有些人认为应该尽量减少手写循环的使用,以支持算法。但是,幸运的是,可能存在不止一种意见,如果标准试图强制执行“无原始循环”,那么可能永远不会包含基于范围的 for 循环。
【讨论】:
以上是关于在啥情况下你应该更喜欢使用 std::copy 写入 cout?的主要内容,如果未能解决你的问题,请参考以下文章
在啥情况下我应该在 C++ 中使用 memcpy 而不是标准运算符?
在使用 boost 共享互斥锁时,我应该在啥情况下使用 owns_lock() 函数
在啥情况下 do-while 可以比 while 更有效率?