2016-06-07 5 views
0

Как я знаю, мы можем использовать ostream_iterator в C++ 11 для печати контейнера.
Например,
Когда использовать 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 эта копия реализована аналогично вашей автоматической петле. Он также специализируется на различных типах работы как можно эффективнее. С другой стороны, запись в 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, поэтому во время выполнения вы можете изменить или пропустить итератор для записи в тип выходного потока разности, основанный на контексте, на котором работают функции.

второй фрагмент использует hardcoded std::cout, который не может меняться во время выполнения.