C++ overloading += operator in custom string class better implementation I am trying to learn C++, so I started coding a custom string class (using only c-style strings) to get familiar with concepts like operator overloading etc. in the case we have a pointer attribute. I wanted to know if there is a smarter/better/neater way to implement the += operator (or the others).
So I am basically defining a private char pointer to store the c-style string, two constructors (empty, char* arg), a copy constructor, a move constructor, a destructor (to deallocate the allocated space from the heap) and two operators (to concatenate strings).
mystring.h
#include &lt;iostream&gt;
#include &lt;cstring&gt;

class mystring
{
private:
    char* str;

public:
    mystring();
    mystring(char* str);
    mystring(const mystring &amp;s);
    mystring(mystring &amp;&amp;s) noexcept;
    ~mystring();

    mystring&amp; operator=(const mystring &amp;s);
    friend std::ostream&amp; operator&lt;&lt;(std::ostream &amp;out, const mystring &amp;s);

    mystring operator+(const mystring &amp;s);
    mystring&amp; operator+=(const mystring &amp;s);
};

mystring.cpp
#include &quot;mystring.h&quot;

mystring::mystring() : mystring(nullptr) {};

mystring::mystring(char* str) : str{nullptr}
{
    if(str == nullptr){
        this-&gt;str = new char;
        this-&gt;str = '\0';
    }else {
        this-&gt;str = new char[strlen(str) + 1];
        strcpy(this-&gt;str, str);
    }
}

// Deep copy
mystring::mystring(const mystring &amp;s) : str{nullptr}
{
    if(str == nullptr){
        this-&gt;str = new char;
        *(this-&gt;str) = '\0';
    }else {
        this-&gt;str = new char[strlen(s.str) + 1];
        strcpy(this-&gt;str, s.str);
    }
}

// Move constructor
mystring::mystring(mystring &amp;&amp;s) noexcept : str{s.str} { s.str = nullptr; }


mystring::~mystring() { delete [] str; }


mystring&amp; mystring::operator=(const mystring &amp;s){
    if(this != &amp;s){
        this-&gt;str = new char[strlen(s.str) + 1];
        strcpy(this-&gt;str, s.str); 
    }

    return *this;
}

std::ostream&amp; operator&lt;&lt;(std::ostream &amp;out, const mystring &amp;s){
    out &lt;&lt; s.str;
    return out;
}


mystring mystring::operator+(const mystring &amp;s){
    mystring concat;
    concat.str = new char[strlen(this-&gt;str) + strlen(s.str) + 1];
    strcpy(concat.str, this-&gt;str);
    strcat(concat.str, s.str);
    return concat;
}

mystring&amp; mystring::operator+=(const mystring &amp;s){
    
    // temp save &quot;this&quot; string to other
    mystring other {new char(strlen(this-&gt;str) + 1)};
    strcpy(other.str, this-&gt;str);

    // allocate space for the concatenated string
    this-&gt;str = new char[strlen(this-&gt;str) + strlen(s.str) + 1];

    // move &quot;this&quot; and input strings to &quot;this&quot;
    strcpy(this-&gt;str, other.str);
    strcat(this-&gt;str, s.str);
    
    return *this;
}
You did a single-null-allocation correctly(ish) once:
if(str == nullptr){
    this-&gt;str = new char;
    *(this-&gt;str) = '\0';

and incorrectly a second time:
if(str == nullptr){
    this-&gt;str = new char;
    this-&gt;str = '\0';

This will produce a memory leak. That aside, if your compiler allowed this without yelling about incompatible types, that makes me sad.
Even then, as @TobySpeight indicates, the first style of allocation has a mismatch with your delete[] and also needs to follow array-like syntax.