title: How can I further improve the efficiency and speed of my string class
body: <p>I was inspired by CString class in MFC. After I understood the principle of that class, especially CopyBeforeWrite technology. I attempted to further improve its efficiency. So I wrote an EspString class.</p>
  <p>In CString, there is a CStringData for sharing buffer when assigned a already existed CString object to a new one. Specifically, when we wrote CString szNew(szOld) or CString szNew = szOld, initially, they share the same buffer, until one of them is modified (that it will call CopyBeforeWrite function, allocate to a new buffer and allow CStringData::nRef-1).</p>
  <p>My code: (most of them are repeated, I inserted the data to struct rather than use (char*)(this+1) to connect).</p>
  <p>Storage Struct:</p>
  <pre><code>struct EspStringInfo{
  /// &lt;summary&gt;
  /// &gt; 1 : The buffer is being shared and still can be shared for new string class.
  /// = 1 : The buffer can be shared, while it is not shared currently. The initial string will be this value.
  /// = -1: The buffer is locked. Although it can be modified, it cannot be shared to any other class. 
  /// &lt;/summary&gt;
  long m_nRef;
  unsigned int m_nStrLen;
  unsigned int m_nBufSize;
  char* m_pszStr;};
  </code></pre>
  <p>Two Global Variables:</p>
  <pre><code>int g_pNullStringData[] = { -1,0,0,NULL };
  EspStringInfo* g_pNullStringInfo = (EspStringInfo*)g_pNullStringData;
  </code></pre>
  <p>Constructor: (Given the character limit, I only provide some of them, while the principle is similar)</p>
  <pre><code>EspString(const char&amp; nCh, unsigned int nChCount)
  {
      assert(nCh != 0);
      this-&gt;m_pStrInfo = new EspStringInfo;
      this-&gt;m_pStrInfo-&gt;m_nRef = 1;
      this-&gt;m_pStrInfo-&gt;m_nStrLen = nChCount;
      this-&gt;m_pStrInfo-&gt;m_nBufSize = nChCount * 2;
      this-&gt;m_pStrInfo-&gt;m_pszStr = new char[this-&gt;m_pStrInfo-&gt;m_nBufSize * sizeof(char)];
      for (unsigned int I = 0; I &lt; nChCount; ++I)
          this-&gt;m_pStrInfo-&gt;m_pszStr[I] = nCh;
      ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, 0, (this-&gt;m_pStrInfo-&gt;m_nBufSize - this-&gt;m_pStrInfo-&gt;m_nStrLen) * sizeof(char));
  }
  
  EspString(const EspString&amp; szStr)
  {
      if (szStr.m_pStrInfo == g_pNullStringInfo)
      {
          this-&gt;m_pStrInfo = g_pNullStringInfo;
          return;
      }
      if (szStr.m_pStrInfo-&gt;m_nRef &gt;= 1)
      {
          this-&gt;m_pStrInfo = szStr.m_pStrInfo;
          ::InterlockedIncrement(&amp;szStr.m_pStrInfo-&gt;m_nRef);
      }
      else
      {
          unsigned int nBufSize = szStr.m_pStrInfo-&gt;m_nStrLen * 2;
          this-&gt;m_pStrInfo = new EspStringInfo;
          this-&gt;m_pStrInfo-&gt;m_nRef = 1;
          this-&gt;m_pStrInfo-&gt;m_nStrLen = szStr.m_pStrInfo-&gt;m_nStrLen;
          this-&gt;m_pStrInfo-&gt;m_nBufSize = nBufSize;
          this-&gt;m_pStrInfo-&gt;m_pszStr = new char[nBufSize * sizeof(char)];
          ::memcpy(this-&gt;m_pStrInfo-&gt;m_pszStr, szStr.m_pStrInfo-&gt;m_pszStr, szStr.m_pStrInfo-&gt;m_nStrLen * sizeof(char));
          ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + szStr.m_pStrInfo-&gt;m_nStrLen, 0, (nBufSize - szStr.m_pStrInfo-&gt;m_nStrLen) * sizeof(char));
      }
  }
  </code></pre>
  <p>Destructor:</p>
  <pre><code>~EspString()
  {
      if (this-&gt;m_pStrInfo != g_pNullStringInfo)
      {
          if (::InterlockedDecrement(&amp;this-&gt;m_pStrInfo-&gt;m_nRef) &lt; 1)
          {
              delete[] this-&gt;m_pStrInfo-&gt;m_pszStr;
              delete this-&gt;m_pStrInfo;
          }
      }
  }
  </code></pre>
  <p>Append: (e.g. szStr=&quot;1234&quot;; szStr.Append(&quot;56&quot;) and then szStr=&quot;123456&quot; )</p>
  <pre><code>EspString&amp; Append(const char&amp; nCh, unsigned int nCount)
  {
      if (nCh == 0)
          return *this;
  
      if (this-&gt;m_pStrInfo == g_pNullStringInfo)
      {
          this-&gt;m_pStrInfo = new EspStringInfo;
          this-&gt;m_pStrInfo-&gt;m_nRef = 1;
          this-&gt;m_pStrInfo-&gt;m_nStrLen = nCount;
          this-&gt;m_pStrInfo-&gt;m_nBufSize = nCount * 2;
          this-&gt;m_pStrInfo-&gt;m_pszStr = new char[this-&gt;m_pStrInfo-&gt;m_nBufSize * sizeof(char)];
          ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr, nCh, nCount * sizeof(char));
          ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + nCount, 0, nCount * sizeof(char));
      }
      else
      {
          unsigned int nStrLen = this-&gt;m_pStrInfo-&gt;m_nStrLen + nCount;
          if (this-&gt;m_pStrInfo-&gt;m_nRef &gt; 1)
          {
              unsigned int nBufSize = nStrLen * 2;
              EspStringInfo* pNewStrInfo = new EspStringInfo;
              pNewStrInfo-&gt;m_nRef = 1;
              pNewStrInfo-&gt;m_nStrLen = nStrLen;
              pNewStrInfo-&gt;m_nBufSize = nBufSize;
              pNewStrInfo-&gt;m_pszStr = new char[nBufSize * sizeof(char)];
              ::memcpy(pNewStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
              ::memset(pNewStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, nCh, nCount * sizeof(char));
              ::memset(pNewStrInfo-&gt;m_pszStr + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
              ::InterlockedDecrement(&amp;this-&gt;m_pStrInfo-&gt;m_nRef);
              this-&gt;m_pStrInfo = pNewStrInfo;
          }
          else
          {
              if (nStrLen &lt; this-&gt;m_pStrInfo-&gt;m_nBufSize)
              {
                  ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, nCh, nCount * sizeof(char));
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
              }
              else
              {
                  unsigned int nBufSize = nStrLen * 2;
                  char* pszNewBuf = new char[nBufSize * sizeof(char)];
                  ::memcpy(pszNewBuf, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
                  ::memset(pszNewBuf + this-&gt;m_pStrInfo-&gt;m_nStrLen, nCh, nCount * sizeof(char));
                  ::memset(pszNewBuf + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
                  delete[] this-&gt;m_pStrInfo-&gt;m_pszStr;
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
                  this-&gt;m_pStrInfo-&gt;m_nBufSize = nBufSize;
                  this-&gt;m_pStrInfo-&gt;m_pszStr = pszNewBuf;
              }
          }
      }
      return *this;
  }
  EspString&amp; Append(const char* pszStr)
  {
      if (pszStr == NULL)
          return *this;
  
      unsigned int nNewStrLen = ::lstrlenA(pszStr);
  
      if (this-&gt;m_pStrInfo == g_pNullStringInfo)
      {
          this-&gt;m_pStrInfo = new EspStringInfo;
          this-&gt;m_pStrInfo-&gt;m_nRef = 1;
          this-&gt;m_pStrInfo-&gt;m_nStrLen = nNewStrLen;
          this-&gt;m_pStrInfo-&gt;m_nBufSize = nNewStrLen * 2;
          this-&gt;m_pStrInfo-&gt;m_pszStr = new char[this-&gt;m_pStrInfo-&gt;m_nBufSize * sizeof(char)];
          ::memcpy(this-&gt;m_pStrInfo-&gt;m_pszStr, pszStr, nNewStrLen * sizeof(char));
          ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + nNewStrLen, 0, nNewStrLen * sizeof(char));
      }
      else
      {
          unsigned int nStrLen = this-&gt;m_pStrInfo-&gt;m_nStrLen + nNewStrLen;
          if (this-&gt;m_pStrInfo-&gt;m_nRef &gt; 1)
          {
              unsigned int nBufSize = nStrLen * 2;
              EspStringInfo* pNewStrInfo = new EspStringInfo;
              pNewStrInfo-&gt;m_nRef = 1;
              pNewStrInfo-&gt;m_nStrLen = nStrLen;
              pNewStrInfo-&gt;m_nBufSize = nBufSize;
              pNewStrInfo-&gt;m_pszStr = new char[nBufSize * sizeof(char)];
              ::memcpy(pNewStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
              ::memcpy(pNewStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, pszStr, nNewStrLen * sizeof(char));
              ::memset(pNewStrInfo-&gt;m_pszStr + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
              ::InterlockedDecrement(&amp;this-&gt;m_pStrInfo-&gt;m_nRef);
              this-&gt;m_pStrInfo = pNewStrInfo;
          }
          else
          {
              if (nStrLen &lt; this-&gt;m_pStrInfo-&gt;m_nBufSize)
              {
                  ::memcpy(this-&gt;m_pStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, pszStr, nNewStrLen * sizeof(char));
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
              }
              else
              {
                  unsigned int nBufSize = nStrLen * 2;
                  char* pszNewBuf = new char[nBufSize * sizeof(char)];
                  ::memcpy(pszNewBuf, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
                  ::memcpy(pszNewBuf + this-&gt;m_pStrInfo-&gt;m_nStrLen, pszStr, nNewStrLen * sizeof(char));
                  ::memset(pszNewBuf + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
                  delete[] this-&gt;m_pStrInfo-&gt;m_pszStr;
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
                  this-&gt;m_pStrInfo-&gt;m_nBufSize = nBufSize;
                  this-&gt;m_pStrInfo-&gt;m_pszStr = pszNewBuf;
              }
          }
      }
      return *this;
  }
  EspString&amp; Append(const EspString&amp; szStr)
  {
      if (szStr.m_pStrInfo == g_pNullStringInfo)
          return *this;
  
      unsigned int nNewStrLen = szStr.m_pStrInfo-&gt;m_nStrLen;
  
      if (this-&gt;m_pStrInfo == g_pNullStringInfo)
      {
          this-&gt;m_pStrInfo = new EspStringInfo;
          this-&gt;m_pStrInfo-&gt;m_nRef = 1;
          this-&gt;m_pStrInfo-&gt;m_nStrLen = nNewStrLen;
          this-&gt;m_pStrInfo-&gt;m_nBufSize = nNewStrLen * 2;
          this-&gt;m_pStrInfo-&gt;m_pszStr = new char[this-&gt;m_pStrInfo-&gt;m_nBufSize * sizeof(char)];
          ::memcpy(this-&gt;m_pStrInfo-&gt;m_pszStr, szStr.m_pStrInfo-&gt;m_pszStr, nNewStrLen * sizeof(char));
          ::memset(this-&gt;m_pStrInfo-&gt;m_pszStr + nNewStrLen, 0, nNewStrLen * sizeof(char));
      }
      else
      {
          unsigned int nStrLen = this-&gt;m_pStrInfo-&gt;m_nStrLen + nNewStrLen;
          if (this-&gt;m_pStrInfo-&gt;m_nRef &gt; 1)
          {
              unsigned int nBufSize = nStrLen * 2;
              EspStringInfo* pNewStrInfo = new EspStringInfo;
              pNewStrInfo-&gt;m_nRef = 1;
              pNewStrInfo-&gt;m_nStrLen = nStrLen;
              pNewStrInfo-&gt;m_nBufSize = nBufSize;
              pNewStrInfo-&gt;m_pszStr = new char[nBufSize * sizeof(char)];
              ::memcpy(pNewStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
              ::memcpy(pNewStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, szStr.m_pStrInfo-&gt;m_pszStr, nNewStrLen * sizeof(char));
              ::memset(pNewStrInfo-&gt;m_pszStr + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
              ::InterlockedDecrement(&amp;this-&gt;m_pStrInfo-&gt;m_nRef);
              this-&gt;m_pStrInfo = pNewStrInfo;
          }
          else
          {
              if (nStrLen &lt; this-&gt;m_pStrInfo-&gt;m_nBufSize)
              {
                  ::memcpy(this-&gt;m_pStrInfo-&gt;m_pszStr + this-&gt;m_pStrInfo-&gt;m_nStrLen, szStr.m_pStrInfo-&gt;m_pszStr, nNewStrLen * sizeof(char));
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
              }
              else
              {
                  unsigned int nBufSize = nStrLen * 2;
                  char* pszNewBuf = new char[nBufSize * sizeof(char)];
                  ::memcpy(pszNewBuf, this-&gt;m_pStrInfo-&gt;m_pszStr, this-&gt;m_pStrInfo-&gt;m_nStrLen * sizeof(char));
                  ::memcpy(pszNewBuf + this-&gt;m_pStrInfo-&gt;m_nStrLen, szStr.m_pStrInfo-&gt;m_pszStr, nNewStrLen * sizeof(char));
                  ::memset(pszNewBuf + nStrLen, 0, (nBufSize - nStrLen) * sizeof(char));
                  delete[] this-&gt;m_pStrInfo-&gt;m_pszStr;
                  this-&gt;m_pStrInfo-&gt;m_nStrLen = nStrLen;
                  this-&gt;m_pStrInfo-&gt;m_nBufSize = nBufSize;
                  this-&gt;m_pStrInfo-&gt;m_pszStr = pszNewBuf;
              }
          }
      }
      return *this;
  }
  </code></pre>
  <p>There are also some other method, and there is the general process:</p>
  <ol>
  <li>Judge the m_pStrInfo is g_pNullStringInfo, all null string will point to this pointer.</li>
  <li>if m_nRef&gt;1, the buffer is being shared.</li>
  <li>the buffer is not shared.</li>
  </ol>
  <p>I wrote this project because in my project the string class have to be assigned to a new object for a lots of times. In the past, the buffer has to be allocated repeatedly and it will waste lots of resources and time. Have there some ways to further improve the efficiency? Thanks for the reply!!!!!!!</p>