A better suggestion might be D-style strings, which are dynamic arrays of char. In D, a dynamic array is a (pointer, length) tuple. This gives you the ability to work on substrings without having to allocate new memory, since a substring is nothing more than a new reference to the same character data.
(Incidentally, Java strings work the same way behind the scenes, but are immutable, which I guess is what you object to when you call them inefficient?)
Of course, one problem with this suggestion is that it doubles the size of a string reference (8 bytes on 32-bit architechtures, 16 bytes on 64 bit architechtures).