Here Stroustrup has reference counting when implementing the String class.
// String.h #include <cstring> #include <iostream> #define DEBUG #ifndef DEFINE_STRING #define DEFINE_STRING class String { struct Srep { char* s; int n; int sz; Srep(int, const char*); ~Srep() { delete[] s; } Srep* GetOwnCopy(); void Assign(int, const char*); private: Srep(const Srep&); Srep& operator=(const Srep&); }; class Cref { public: inline Cref(String&, int); inline Cref(const Cref&); Cref(); inline operator char() const; inline void operator=(char); private: String& s; int i; }; public: class Range { }; inline String(); inline String(const char*); String(const String&); ~String(); String& operator=(const char*); String& operator=(const String&); inline void Check(int) const; inline char Read(int) const; inlinevoid Write(int, char); inline Cref operator[](int); inline char operator[](int) const; inline int Size() const; private: Srep* rep; }; inline String::String() : rep(new Srep(0, "") ) { #ifdef DEBUG std::cout << "inline String::String()" << std::endl; #endif } inline String::String(const char* p) : rep(new Srep(strlen(p), p) ) { #ifdef DEBUG std::cout << "inline String::String(const char* p)" << std::endl; #endif } inline void String::Check(int i) const { #ifdef DEBUG std::cout << "inline void String::Check(int i) const" << std::endl; #endif if (i < 0 || rep->sz <= i) throw Range(); } inline char String::Read(int i) const { #ifdef DEBUG std::cout << "inline char String::Read(int i) const" << std::endl; #endif return rep->s[i]; } inline void String::Write(int i, char c) { #ifdef DEBUG std::cout << "inline void String::Write(int i, char c)" << std::endl; #endif rep = rep->GetOwnCopy(); rep->s[i] = c; } inline String::Cref String::operator[](int i) { #ifdef DEBUG std::cout << "inline String::Cref String::operator[](int i)" << std::endl; #endif Check(i); return Cref(*this, i); } inline char String::operator[](int i) const { #ifdef DEBUG std::cout << "inline char String::operator[](int i) const" << std::endl; #endif Check(i); return rep->s[i]; } inline int String::Size() const { #ifdef DEBUG std::cout << "inline int String::Size() const" << std::endl; #endif return rep->sz; } inline String::Cref::Cref(String& ss, int ii) : s(ss), i(ii) { #ifdef DEBUG std::cout << "inline String::Cref::Cref(String& ss, int ii)" << std::endl; #endif } inline String::Cref::Cref(const Cref& r) : s(rs), i(ri) { #ifdef DEBUG std::cout << "inline String::Cref::Cref(const Cref& r)" << std::endl; #endif } inline String::Cref::operator char() const { #ifdef DEBUG std::cout << "inline String::Cref::operator char() const" << std::endl; #endif s.Check(i); return s.Read(i); } inline void String::Cref::operator=(char c) { #ifdef DEBUG std::cout << "inline void String::Cref::operator=(char c)" << std::endl; #endif s.Write(i, c); } #endif // String.cpp #include "String.h" String::String(const String& r) { #ifdef DEBUG std::cout << "String::String(const String& r)" << std::endl; #endif r.rep->n++; rep = r.rep; } String::~String() { #ifdef DEBUG std::cout << "String::~String()" << std::endl; #endif if (--rep->n == 0) delete rep; } String& String::operator=(const char* p) { #ifdef DEBUG std::cout << "String& String::operator=(const char* p)" << std::endl; #endif if (rep->n == 1) rep->Assign(strlen(p), p); else { rep->n--; rep = new Srep(strlen(p), p); } return *this; } String& String::operator=(const String& r) { #ifdef DEBUG std::cout << "String& String::operator=(const String& r)" << std::endl; #endif r.rep->n++; if (--rep->n == 0) delete rep; rep = r.rep; return *this; } String::Srep::Srep(int nsz, const char* p) { #ifdef DEBUG std::cout << "String::Srep::Srep(int nsz, const char* p)" << std::endl; #endif n = 1; sz = nsz; s = new char[sz + 1]; strcpy(s, p); } String::Srep* String::Srep::GetOwnCopy() { #ifdef DEBUG std::cout << "String::Srep* String::Srep::GetOwnCopy()" << std::endl; #endif if (n == 1) return this; n--; return new Srep(sz, s); } void String::Srep::Assign(int nsz, const char* p) { #ifdef DEBUG std::cout << "void String::Srep::Assign(int nsz, const char* p)" << std::endl; #endif if (nsz != sz) { delete[] s; sz = nsz; s = new char[sz + 1]; } strcpy(s, p); }