为啥我需要另一个迭代器作为 std::copy() 中的参数?
Posted
技术标签:
【中文标题】为啥我需要另一个迭代器作为 std::copy() 中的参数?【英文标题】:Why do I need another iterator as an argument in std::copy()?为什么我需要另一个迭代器作为 std::copy() 中的参数? 【发布时间】:2019-09-10 08:02:43 【问题描述】:我不明白为什么我需要在调用std::copy()
时将另一个迭代器作为第二个参数来读取文件。文件的迭代器“结束”如何结束?
vector<Point> v;
istream_iterator<Point> is(file), end;
copy(is, end, back_inserter(v));
【问题讨论】:
一个范围需要分:开始和结束。如果没有结束,std::copy
怎么知道什么时候停止复制?
【参考方案1】:
文件的迭代器'end'如何结束?
按照惯例和/或标准库中的设计决定。迭代器end
是默认构造的,在cppreference 上,我们了解了默认的std:istream_iterator
构造函数:
constexpr istream_iterator();
构造流结束迭代器,对存储的值进行值初始化[...]
更深层的原因是标准算法是围绕半开范围的概念构建的,通常表示为[first, last)
。 is
迭代器必须与某种结束标记 last
区分开来 - 否则,std::copy
无法知道何时从输入中读取不再有意义(即,何时到达文件末尾)。在你的情况下,这是end
。
【讨论】:
也就是说,它只需要另一个迭代器作为比较? 是的。查看std::copy
的示例实现:主循环将first
与last
进行比较,其中last
是您的end
。【参考方案2】:
为什么?
您需要以某种方式告诉算法它应该复制多少个元素。请注意,copy
是通用的,使用迭代器的原因是与实际容器无关。因此,算法在到达容器末端时无法停止。它所拥有的只是你传递给它的两个迭代器。
怎么做?
这就是它在语言中的定义方式。如果您查看不带参数的构造函数,您会发现它创建了一个特殊的流结束迭代器。来自cppreference:
constexpr istream_iterator(); (1)
1) 构造流结束迭代器,对存储的值进行值初始化。如果定义 auto x = T(); 中的初始值设定项,则此构造函数为 constexpr;是一个常量初始化器。
【讨论】:
【参考方案3】:我相信问题是问为什么std::copy
在文件中遇到实际的EOF
(文件结尾)字符时不只是停止复制,而不是人为地传入默认构造的方法迭代器。
std::copy
是一种通用算法,适用于许多具有迭代器的容器。从向量或数组复制需要开始和结束输入迭代器,因为在向量和数组中没有对应的 EOF 标记。由于我们想对文件使用相同的copy
程序,因此文件迭代器只是用于此目的,并且实现可能会执行类似
如果文件迭代器指向
EOF
,则将其设置为默认构造值
这当然是微不足道的。当然,是可以有一个类似file_copy(file, destination)
的函数,但是它会是一个不同于我们习惯的标准std::copy
的接口,并且我们将对文件使用不同的copy
函数,就像我们对数组和向量所做的那样。
【讨论】:
以上是关于为啥我需要另一个迭代器作为 std::copy() 中的参数?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 std::copy 期间使用 std::back_inserter 而不是 end()?