A mutable 'C String' wrapper for a C++ std::string

Bench 0 Tallied Votes 939 Views Share

The C++ string type can be converted to a const null-terminated string using .c_str() for interoperability with legacy C code. However, this poses a potential problem when mixing std::string with functions designed to mutate a string in-place.

a const_cast to get around this issue results in undefined behaviour, since the underlying representation of a std::string may or may not be null terminated. The ideal solution is to rewrite legacy code into C++, but this isn't always possible (For example, if the legacy code is part of a dynamically linked library) so a typical workaround is to allocate enough space to copy the C++ string into, then work with a non-const char*, before copying the the result back into the C++ string. these extra steps can be encapsulated into a wrapper class.

(This example demonstrated using Dave Sinkula's C string reversal function: http://www.daniweb.com/code/snippet216514.html )
Exactly what the legacy C function does is irrelevent here - the important outcome is that the code calling mystrrev() is not cluttered by memory management or string copying - instead, mystrrev() is passed a temporary c_string buffer which refers to the C++ string - when mystrrev finishes, the c_string automatically updates the original C++ string.

This wrapper class was born out of a need to convert legacy C-based code into C++ code, without needing to add clutter or to rewrite tried-and-tested functions

#include <string>
#include <cstring>
#include <iostream>

class c_string
    std::string& cpp_str;
    char* mutable_str;
    c_string(const c_string&);
    c_string& operator=(const c_string&);
    c_string(std::string& s)
        : cpp_str(s)
        , mutable_str( new char[s.size()+1] ) 
        std::strncpy(mutable_str, s.c_str(), s.size()+1);
    operator char*&() { return mutable_str; }
        cpp_str = mutable_str;
        delete [] mutable_str; 

/* Example of 'C' Code to mutate a C string
 * - Credit to Dave Sinkula 
 * - http://www.daniweb.com/code/snippet216514.html
void mystrrev(char *s)
   char *t = s;
   while ( *t != '\0' ) ++t;
   for ( --t; s < t; ++s, --t )
      char temp = *s;
      *s = *t;
      *t = temp;

int main()
    std::string str = "Backwards?";
    std::cout << str << std::endl;  

    mystrrev( c_string(str) );
    std::cout << str << std::endl;