In C++, Output Iterators are a type of iterator used to write data to a container or stream, moving in a single direction.
They are primarily used to insert or modify elements in containers or output streams.
Unlike input iterators, which are read-only, output iterators are write-only and do not allow for reading or comparing elements.
Output iterators are especially useful for algorithms that produce or transform data.
Characteristics of Output Iterators
- Single-pass traversal: Can only move forward, similar to input iterators.
- Write-only: Only supports writing elements, not reading them.
- No comparison: Output iterators cannot be compared for equality or inequality.
- Dereferenceable: Supports dereferencing for writing data.
Basic Syntax
iterator_type iterator_name = container.begin();
1. Basic Example of Output Iterator with std::vector
In this example, an output iterator is used to add elements to a std::vector.
#include <iostream> #include <vector> #include <iterator> using namespace std; int main() { vector<int> numbers; // Output iterator to insert elements into the vector back_insert_iterator<vector<int>> output_it(numbers); *output_it = 10; // Insert 10 ++output_it; *output_it = 20; // Insert 20 ++output_it; *output_it = 30; // Insert 30 cout << "Vector elements: "; for (int number : numbers) { cout << number << " "; } return 0; }
Explanation:
- back_insert_iterator<vector<int>> is used to create an output iterator that inserts elements at the end of numbers.
- Each *output_it = value operation inserts the value at the current iterator position.
Output:
Vector elements: 10 20 30
2. Using std::ostream_iterator for Stream Output
std::ostream_iterator is an output iterator that writes elements to output streams, like cout.
#include <iostream> #include <iterator> #include <vector> using namespace std; int main() { vector<int> numbers = {1, 2, 3, 4, 5}; cout << "Vector elements: "; ostream_iterator<int> output_it(cout, " "); for (int number : numbers) { *output_it = number; // Write each element to cout ++output_it; } return 0; }
Explanation:
- ostream_iterator<int> output_it(cout, ” “); creates an output iterator that writes integers to cout, separated by a space.
- Each *output_it = number operation outputs the value to the console.
Output:
Vector elements: 1 2 3 4 5
3. Copying Elements to std::vector Using std::copy and back_inserter
std::copy can be used with back_inserter to copy elements from one container to another.
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> numbers = {1, 2, 3, 4, 5}; vector<int> new_numbers; // Use std::copy with back_inserter copy(numbers.begin(), numbers.end(), back_inserter(new_numbers)); cout << "New vector elements: "; for (int number : new_numbers) { cout << number << " "; } return 0; }
Explanation:
- back_inserter(new_numbers) creates an output iterator that appends elements to new_numbers.
- std::copy copies elements from numbers to new_numbers using this output iterator.
Output:
New vector elements: 1 2 3 4 5
4. Using std::fill_n with Output Iterators
The std::fill_n algorithm can be used with output iterators to add a fixed number of elements to a container.
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> numbers; // Fill the vector with five 100s fill_n(back_inserter(numbers), 5, 100); cout << "Filled vector elements: "; for (int number : numbers) { cout << number << " "; } return 0; }
Explanation:
- fill_n(back_inserter(numbers), 5, 100); fills numbers with five instances of 100 using a back-insert output iterator.
Output:
Filled vector elements: 100 100 100 100 100
5. Writing to std::ofstream Using std::ostream_iterator
ostream_iterator can also be used with file streams to write elements to a file.
#include <iostream> #include <fstream> #include <iterator> #include <vector> using namespace std; int main() { ofstream outputFile("output.txt"); if (!outputFile) { cerr << "File could not be opened!" << endl; return 1; } vector<int> numbers = {1, 2, 3, 4, 5}; ostream_iterator<int> output_it(outputFile, "\n"); for (int number : numbers) { *output_it = number; ++output_it; } outputFile.close(); cout << "Numbers written to file output.txt" << endl; return 0; }
Explanation:
- ostream_iterator<int> output_it(outputFile, “\n”); creates an output iterator that writes each integer to a new line in output.txt.
- Each *output_it = number writes the number to the file.
Output:
Numbers written to file output.txt
Content of output.txt:
1 2 3 4 5
6. Using std::transform with Output Iterators
The std::transform function applies a transformation to elements and stores the result using an output iterator.
#include <iostream> #include <vector> #include <iterator> #include <algorithm> using namespace std; int main() { vector<int> numbers = {1, 2, 3, 4, 5}; vector<int> squaredNumbers; // Square each element and store in squaredNumbers transform(numbers.begin(), numbers.end(), back_inserter(squaredNumbers), [](int n) { return n * n; }); cout << "Squared elements: "; for (int number : squaredNumbers) { cout << number << " "; } return 0; }
Explanation:
- transform squares each element in numbers and uses back_inserter to store results in squaredNumbers.
Output:
Squared elements: 1 4 9 16 25
7. Using std::generate_n with Output Iterators
The std::generate_n function generates a sequence of values and stores them in a container using an output iterator.
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> numbers; // Generate sequence of 5 random numbers generate_n(back_inserter(numbers), 5, []() { return rand() % 100; }); cout << "Generated random numbers: "; for (int number : numbers) { cout << number << " "; } return 0; }
Explanation:
- generate_n uses back_inserter(numbers) to add five random numbers to numbers.
Output (random values):
Generated random numbers: 37 23 88 19 45
8. Duplicating Elements with std::copy and std::ostream_iterator
You can duplicate elements from one container to another using std::copy and output iterators.
#include <iostream> #include <vector> #include <iterator> #include <algorithm> using namespace std; int main() { vector<int> numbers = {1, 2, 3}; cout << "Duplicated elements: "; copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " ")); copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " ")); // Copy again to duplicate return 0; }
Explanation:
- copy is called twice, each time outputting numbers to cout.
Output:
Duplicated elements: 1 2 3 1 2 3
Summary Table of Output Iterator Usage
Example | Description |
---|---|
Basic Vector Output Iterator | Inserts elements into a vector |
Stream Output Iterator | Writes elements to cout using ostream_iterator |
Copying with std::copy | Copies elements to a new container with back_inserter |
Filling with std::fill_n | Fills a container with repeated values |
File Output with ostream_iterator | Writes elements to a file using an output iterator |
Transforming with std::transform | Transforms and stores results in another container |
Generating Sequence | Generates values and stores them in a container |
Duplicating Elements | Duplicates container contents using output iterators |
Key Takeaways
- Output Iterators are used to write or insert data into containers or streams.
- std::back_inserter and std::ostream_iterator are common types of output iterators used for appending elements and writing to streams.
- Output iterators work well with algorithms like std::copy, std::fill_n, std::transform, and std::generate_n.
- Unlike other iterators, output iterators are write-only and are not used for reading or comparing elements, making them suitable for single-pass write operations.