This article has been originally posted on my blog. If you would like to receive my latest articles, please sign up to my newsletter.
In this next part of the big STL algorithm tutorial, we will continue with two algorithms that help us to reverse the order of elements in a range:
reverse
reverse_copy
Let's get started!
reverse
It's as simple as you can imagine - by an STL algorithm. It takes a range defined by a pair of iterators and reverses the range, in place. It doesn't even have a return value. The only thing you have to pay attention to is to pass in the right iterators.
#include <iostream>
#include <algorithm>
#include <vector>
int main () {
std::vector<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::reverse(numbers.begin(),numbers.end());
std::cout << "numbers of original vector are reversed: ";
for (auto number : numbers) {
std::cout << ' ' << number;
}
std::cout << std::endl;
return 0;
}
reverse_copy
This algorithm is not much more complicated than reserve
. The only difference is that, while reverse
made in-place changes to a container, reverse_copy
leaves the input intact and fills up an output container.
As you could have got used to it, the output is passed in by an iterator (here as a third parameter). You either make sure that the container under the iterator is big enough to accommodate all the elements that are going to be inserted or you pass in an iterator that can insert new elements, like in the below example.
#include <iostream>
#include <algorithm>
#include <vector>
int main () {
std::vector<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> reversedNumbers{};
reversedNumbers.reserve(numbers.size());
std::reverse_copy(numbers.begin(),numbers.end(),std::back_inserter(reversedNumbers));
std::cout << "order of numbers in original vector hasn't changes: ";
for (auto number : numbers) {
std::cout << ' ' << number;
}
std::cout << std::endl;
std::cout << "numbers in reversedNumbers are reversed: ";
for (auto number : reversedNumbers) {
std::cout << ' ' << number;
}
std::cout << std::endl;
return 0;
}
You can consider it as a certain part of our immutable programming toolbox, Why just a certain? As STL algorithms operate through iterators, not directly on containers, it cannot return you a new container, but it will modify the one that the passed in iterator points to.
Therefore it's not strongly part of an immutable toolbox, but one can make the point that it just takes a potentially empty container that was created on the line before, and then it should not be modified.
Sadly, your copy cannot be const
given that reverse_copy
already had to modify it. If you really what to show that it's a const vector, you have to wrap the transformation into its own function, somehow like this:
#include <iostream>
#include <algorithm>
#include <vector>
template<typename T>
const std::vector<T> reverse_const_copy(const std::vector<T>& input) {
std::vector<T> reversedInput{};
reversedInput.reserve(input.size());
std::reverse_copy(input.begin(),input.end(),std::back_inserter(reversedInput));
return reversedInput;
}
int main () {
std::vector<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9};
const std::vector<int> reversedNumbers = reverse_const_copy(numbers);
// reversedNumbers.push_back(0); // this does not compile as reversedNumbers is const
std::cout << "order of numbers in original vector hasn't changes: ";
for (auto number : numbers) {
std::cout << ' ' << number;
}
std::cout << std::endl;
std::cout << "numbers in reversedNumbers are reversed: ";
for (auto number : reversedNumbers) {
std::cout << ' ' << number;
}
std::cout << std::endl;
return 0;
}
Conclusion
Today, we learned about 2 algorithms that help us to reverse the elements of a container, I think their usage didn't hide any big surprise. Besides we also saw how we can make const reversed copies, even if it needs some additional tinkering.
Next time we’ll learn about Sean Parent's favourite algorithms rotate
and rotate_copy
. Stay tuned!
Top comments (3)
Hi, Sandor Dargo
I think the code snippets
is changed to as following by adopted keyword
auto
is better.what do you think about this?
Best regards, Gapry.
Thanks for your comment @gapry .
I think that in the second case, it's better and if you are looking for a direct replacement, I would go with
const auto
. If you'd change the return type of reverse_const_copy(), there would be nothing to do on the caller side.In the first case, I don't think it's any better. If you want to change the type, you have to update it anyway and using auto in fact just makes the code more verbose without adding any benefits.
It's debatable that it would make the code more uniform, without any benefits and with a few extra chars, let's say it's a matter of personal preference/project guidelines.
Thanks for your ideas!
Hi, @sandordargo
Thank you for your insights !
Best regards, Gapry.