如何使用STL算法?
std::ifstream file(filename);
std::vector<unsigned char> buf;
for(auto file_it = std::istreambuf_iterator<char>(file); file_it != std::istreambuf_iterator<char>() && buf.size() < 2048; ++file_it)
buf.push_back(*file_it);
注buf.size() < 2048
。
例如,如果我执行以下操作,并且文件小于2048字节,会发生什么?
std::copy_n(std::istreambuf_iterator<char>(file), 2048, std::back_inserter(buf));
正如文档所说,std::copy_n()
将完全复制n
项。它会一直读到迭代器引用的序列的末尾。不过,我不确定标准对istreambuf_iterator<>
有什么规定。这可能是未定义的行为,但流可能会在结束后生成大量eof()
的副本。当可用的2048
字节不足时,这可能会导致大量垃圾。
在任何情况下,如果您想可靠地复制多达n
项,您需要编写自己的函数:
template<typename I1, typename I2, typename size_type>
I copy_upto_n ( I1 begin, I1 end, size_type n, I2 out )
{
for (size_type i=0; (i < n) && (begin != end); ++i)
{
*out++ = *begin++;
}
return out;
}
有些人可能会使用std::iterator_traits<>
而不是额外的模板参数来强制使用与迭代器相同的距离类型。
您可以使用一个特殊的back_insert_iterator
来丢弃基于谓词的操作。
此代码被无耻地从stdlib并进行了改编。C++03版本应该只需要分配中的Container::const_reference
。
template<typename Container, typename Predicate>
class discarding_back_inserter
: public iterator<output_iterator_tag, void, void, void, void>
{
Container* container;
Predicate p;
public:
typedef Container container_type;
explicit
back_insert_iterator(Container& x, Predicate p) : container(&__x), p(p) { }
back_insert_iterator&
operator=(const typename Container::value_type& value)
{
if(*container)
container->push_back(__value);
return *this;
}
back_insert_iterator&
operator=(typename _Container::value_type&& value)
{
if(*container)
container->push_back(std::move(__value));
return *this;
}
back_insert_iterator&
operator*()
{ return *this; }
back_insert_iterator&
operator++()
{ return *this; }
back_insert_iterator
operator++(int)
{ return *this; }
};