Direct construction

Reverse String
Reverse String in C++

reverse_string.h

#ifndef REVERSE_STRING_H
#define REVERSE_STRING_H

#include <string>

namespace reverse_string
{
    std::string reverse_string(std::string_view str);
}

#endif // REVERSE_STRING_H

reverse_string.cpp

#include "reverse_string.h"

namespace reverse_string
{

// (1) the function takes a std::string_view
std::string reverse_string(std::string_view original)
{
    // (2) construct the reversed string directly
    // by combining a constructor with reverse iterators
    return std::string(rbegin(original), rend(original));
}

} // namespace reverse_string;

The type of the parameter

The function takes a std::string_view as its argument. That type was added to C++17, it is an immutable "view" of a string, it is cheap to construct and to copy (see cppreference.com.) We can use it here because the function does not modify the parameter.

Reverse Iterators

In C++ "normal" iterators are an abstraction of pointers. We can dereference them (if they refer to a valid object), we can compare them, we can increment them so that they refer to the next object, etc. just like with regular pointers. "Reverse iterators" are similar, we can dereference them (if they refer to a valid object), we can compare them, etc. but the direction is reversed: When we increment them they refer to the previous object.

For example:

std::string str = "abcdefghijklmnopqrstuvwxyz";
auto rit = rbegin(str);  // this is a reverse iterator that refers to the last character
std::cout << *rit << '\n';  // prints z
++rit;
std::cout << *rit << '\n';  // prints y

Constructor of std::string

std::string has surprisingly many constructors (see cppreference.com.) One of them takes two iterators (begin and end of a range) and constructs a std::string with the characters in that range.

Combining this constructor with the reverse iterators rbegin(original) and rend(original) creates the reversed string directly.

We could even omit the type std::string from the return statement and write

return {rbegin(original), rend(original)};

That works because the compiler knows the return type of the function and uses the "braced init-list" to construct the std::string.

Conclusion

This is a great approach, it is concise and easy to read (once you know about the constructor and reverse iterators), it is idiomatic and very efficient.

27th Nov 2024 · Found it useful?

Other Approaches to Reverse String in C++

Other ways our community solved this exercise
std::string result;
for (std::size_t i = 0; i < size(original); ++i)
{
    std::size_t rindex = size(original) - i - 1;
    result.append(original[rindex]);
}
return result;
Iterative

Build the reversed string iteratively.

std::size_t a = 0;
std::size_t b = size(str) - 1;
while (a < b)
{
    std::swap(str[a], str[b]);
    ++a; --b;
}
return str;
Swapping characters

Modify the parameter, swapping characters manually.

std::reverse(begin(str), end(str));
Using the standard library

Modify the parameter, using the standard library.

std::string result;
while (!original.empty())
{
    char c = original.back();
    original.remove_suffix(1);
    result.push_back(c);
}
return result;
Stack operations

Build the reversed string with stack operations.

void recursive_helper(std::string_view input, std::string& output)
{
    if (input.empty())
        return;
    output.append(input.back());
    input.remove_suffix(1);
    recursive_helper(input, output);
}
Linear recursion

Build the reversed string with linear recursion.

if (size(original) <= 1)
    return std::string{original};
auto half_size = size(str) / 2;
return reverse_string(original.substr(half_size) +
       reverse_string(original.substr(0, half_size);
Divide and conquer

Build the reversed string recursively, with divide and conquer.

[[nodiscard]] std::string reverse_string(std::string&& str) noexcept;
[[nodiscard]] std::string reverse_string(std::string_view str);
[[nodiscard]] std::string reverse_string(const char* str);
Over-Engineered

Try to achieve peak performance with function overloading.