2016-06-07 59 views
0

据我所知,我们可以在C++ 11中使用ostream_iterator来打印一个容器。
例如,
何时使用ostream_iterator

std::vector<int> myvector; 
for (int i=1; i<10; ++i) myvector.push_back(i*10); 

std::copy (myvector.begin(), myvector.end(), std::ostream_iterator<int>{std::cout, " "}); 

我不知道什么时候,为什么我们使用上面的代码,而不是传统的方式,如:

for(const auto & i : myvector) std::cout<<i<<" "; 

在我看来,传统的方式因为没有copy,我对吗?

回答

1

std::ostream_iterator是一个单通OutputIterator,所以它可以用于接受这种迭代器的任何算法。使用它来输出int-s的向量只是为了展示它的能力。

在我看来,传统方式更快,因为没有副本,我是对吗?

您可能在这里找到:http://en.cppreference.com/w/cpp/algorithm/copy副本的实现与您的for-auto循环非常相似。它也专门为各种类型工作尽可能高效。另一方面写入std :: ostream_iterator是通过赋值给它完成的,你可以在这里阅读:http://en.cppreference.com/w/cpp/iterator/ostream_iterator/operator%3D,它解析为*out_stream << value;操作(如果分隔符被忽略)。

你也可能会发现这个迭代器会遇到在最后插入的额外尾随分隔符的问题。为了解决这个问题,可能会有(可能在C++ 17中)一个新的是单通的OutputIterator std::experimental::ostream_joiner

一个简短(也许愚蠢)的例子,其中使用迭代器是有用的。关键是您可以将数据导向任何接收器 - 文件,控制台输出,内存缓冲区。无论您选择什么输出,MyData::serialize都不需要更改,您只需提供OutputIterator即可。

struct MyData { 
    std::vector<int> data = {1,2,3,4}; 

    template<typename T> 
    void serialize(T iterator) { 
     std::copy(data.begin(), data.end(), iterator); 
    } 
}; 

int main() 
{ 
    MyData data; 

    // Output to stream 
    data.serialize(std::ostream_iterator<int>(std::cout, ",")); 

    // Output to memory 
    std::vector<int> copy; 
    data.serialize(std::back_inserter(copy)); 

    // Other uses with different iterator adaptors: 
    // std::front_insert_iterator 
    // other, maybe custom ones 
} 
0

不同之处在于多态性与硬编码流。
std::ostream_iterator从继承自std::ostream的任何类构建自己,因此在运行时,您可以更改或线迭代器根据函数运行的上下文写入差异输出流类型。

第二个片段使用硬编码的std::cout,它在运行时不能改变。