Immutable C++ String class I have project where I will need to create lots of immutable strings. If I am using std::string, which has huge overhead - about 60-70% against const char *. On a 64-bit machine, the current implementation uses 8 bytes for the class + the const char * size. This is the same size as it would be with plain C.

I will also do optimization with union and will put small strings into the pointer itself.

I need to know if I am on right track.

#include &lt;stdio.h&gt;

#include &lt;memory&gt;
#include &lt;string.h&gt;

class String{
public:
    String(){};

    String(const char *s) : _data(__dup(s)){};

    String(const String &amp; other) : String( other.c_str() ){};

    String(String &amp;&amp; other) = default;

    String &amp; operator=(String other){
        std::swap(_data, other._data);
        return *this;
    }



    const char *c_str() const{
        return _data.get();
    }

    int cmp(const String &amp; other) const{
        if (c_str() == nullptr)
            return other ? -1 : 0;

        return strcmp(*this, other);
    }

    operator bool() const{
        return c_str();
    }

    operator const char *() const{
        return c_str();
    }



    bool operator == (const String &amp; other) const{
        return cmp(other) == 0;
    }

    bool operator != (const String &amp; other) const{
        return cmp(other) != 0;
    }

    bool operator &gt; (const String &amp; other) const{
        return cmp(other) &gt; 0;
    }

    bool operator &gt;= (const String &amp; other) const{
        return cmp(other) &gt;= 0;
    }

    bool operator &lt; (const String &amp; other) const{
        return cmp(other) &lt; 0;
    }

    bool operator &lt;= (const String &amp; other) const{
        return cmp(other) &lt;= 0;
    }

private:
    static char *__dup(const char *s){
        auto size = strlen(s);
        char *copy = new char[size];
        memcpy(copy, s, size);
        return copy;
    }

private:
    std::unique_ptr&lt;char[]&gt; _data;
};



void p(String &amp;s){
    printf("%s\n", s ? (const char *) s : "[null]");
}

int main(){
    String s1;          p(s1);
    String s2  = { "hello" };   p(s2);
    String s3a = s2;        p(s3a);
    String s3  = std::move(s3a);    p(s3);
    s1 = s3;            p(s1);
    s1 = "hi";          p(s1);

    String a = "aaaa";
    String b = "bbbb";
    String c = "aaaa";

    printf("%s %s\n", a == c ? "Y" : "N", "Y");
    printf("%s %s\n", a == b ? "Y" : "N", "N");
    printf("%s %s\n", a != b ? "Y" : "N", "Y");
    printf("%s %s\n", a &lt;  b ? "Y" : "N", "Y");
    printf("%s %s\n", a &gt;  b ? "Y" : "N", "N");
    printf("%s %s\n", a &lt;= b ? "Y" : "N", "Y");
    printf("%s %s\n", a &gt;= b ? "Y" : "N", "N");
    printf("%s %s\n", a &lt;= c ? "Y" : "N", "Y");
    printf("%s %s\n", a &gt;= c ? "Y" : "N", "Y");

    return 0;
}
Design

In modern standard libraries, std::string uses short string optimization, which allows to avoid heap allocations at all for string shorter then ~20 chars (on 64-bit machines). So you really want to measure performance, I am not readily convinced that your string offers performance improvement. Of course, for your specific use pattern it might, but you have to measure.

__dup function

This is the most problematic part of the code.


Apparently, you forgot to return value from __dup method (now fixed).
You must allocate one char more and fill it with zero. Or copy size+1 characters from the source.
Identifiers with leading double underscores or one leading underscore and a capital letter are reserved by the standard. You must not use such an identifier. It is enough that you already have put it into private section.


After the corrections, the function could look like this:

static char *dup(const char *s){
    auto size = strlen(s);
    char *copy = new char[size + 1];
    memcpy(copy, s, size + 1);
    return copy;
}


Safety

Functions do not check for null pointers. This code will cause illegal memory access:

String x;
String y{x};


Style


You don't need semicolons after the member function definitions
I would recommend not putting methods on a single line even if they have empty bodies.
You can use C++ style headers &lt;cstring&gt; and &lt;cstdio&gt; instead of C-style ones.
I would recommend to implement an operator&lt;&lt;(std::ostream &amp;, const String &amp;) so you could use your string together with iostreams.
For testing, it is better to use a testing framework. Like boost.test, gtest, Catch etc.